* config/msp430/msp430.c (TARGET_WARN_FUNC_RETURN): Define.
[official-gcc.git] / gcc / config / msp430 / msp430.c
blobadde5979c7752d42cdecbf835770dfc7fbf049f8
1 /* Subroutines used for code generation on TI MSP430 processors.
2 Copyright (C) 2012-2018 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)
10 any later version.
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #define IN_TARGET_CODE 1
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "backend.h"
27 #include "target.h"
28 #include "rtl.h"
29 #include "tree.h"
30 #include "stringpool.h"
31 #include "attribs.h"
32 #include "gimple-expr.h"
33 #include "df.h"
34 #include "memmodel.h"
35 #include "tm_p.h"
36 #include "regs.h"
37 #include "emit-rtl.h"
38 #include "diagnostic-core.h"
39 #include "fold-const.h"
40 #include "stor-layout.h"
41 #include "calls.h"
42 #include "output.h"
43 #include "explow.h"
44 #include "expr.h"
45 #include "langhooks.h"
46 #include "builtins.h"
47 #include "intl.h"
49 /* This file should be included last. */
50 #include "target-def.h"
53 static void msp430_compute_frame_info (void);
57 /* Run-time Target Specification. */
59 bool msp430x = true;
61 struct GTY(()) machine_function
63 /* If set, the rest of the fields have been computed. */
64 int computed;
65 /* Which registers need to be saved in the pro/epilogue. */
66 int need_to_save [FIRST_PSEUDO_REGISTER];
68 /* These fields describe the frame layout... */
69 /* arg pointer */
70 /* 2/4 bytes for saved PC */
71 int framesize_regs;
72 /* frame pointer */
73 int framesize_locals;
74 int framesize_outgoing;
75 /* stack pointer */
76 int framesize;
78 /* How much we adjust the stack when returning from an exception
79 handler. */
80 rtx eh_stack_adjust;
83 /* This is our init_machine_status, as set in
84 msp_option_override. */
85 static struct machine_function *
86 msp430_init_machine_status (void)
88 struct machine_function *m;
90 m = ggc_cleared_alloc<machine_function> ();
92 return m;
95 #undef TARGET_OPTION_OVERRIDE
96 #define TARGET_OPTION_OVERRIDE msp430_option_override
98 /* This is a copy of the same data structure found in gas/config/tc-msp430.c
99 Also another (sort-of) copy can be found in gcc/config/msp430/t-msp430
100 Keep these three structures in sync.
101 The data in this structure has been extracted from version 1.194 of the
102 devices.csv file released by TI in September 2016. */
104 struct msp430_mcu_data
106 const char * name;
107 unsigned int revision; /* 0=> MSP430, 1=>MSP430X, 2=> MSP430Xv2. */
108 unsigned int hwmpy; /* 0=>none, 1=>16-bit, 2=>16-bit w/sign extend, 4=>32-bit, 8=> 32-bit (5xx). */
110 msp430_mcu_data [] =
112 { "cc430f5123",2,8 },
113 { "cc430f5125",2,8 },
114 { "cc430f5133",2,8 },
115 { "cc430f5135",2,8 },
116 { "cc430f5137",2,8 },
117 { "cc430f5143",2,8 },
118 { "cc430f5145",2,8 },
119 { "cc430f5147",2,8 },
120 { "cc430f6125",2,8 },
121 { "cc430f6126",2,8 },
122 { "cc430f6127",2,8 },
123 { "cc430f6135",2,8 },
124 { "cc430f6137",2,8 },
125 { "cc430f6143",2,8 },
126 { "cc430f6145",2,8 },
127 { "cc430f6147",2,8 },
128 { "msp430afe221",0,2 },
129 { "msp430afe222",0,2 },
130 { "msp430afe223",0,2 },
131 { "msp430afe231",0,2 },
132 { "msp430afe232",0,2 },
133 { "msp430afe233",0,2 },
134 { "msp430afe251",0,2 },
135 { "msp430afe252",0,2 },
136 { "msp430afe253",0,2 },
137 { "msp430bt5190",2,8 },
138 { "msp430c091",0,0 },
139 { "msp430c092",0,0 },
140 { "msp430c111",0,0 },
141 { "msp430c1111",0,0 },
142 { "msp430c112",0,0 },
143 { "msp430c1121",0,0 },
144 { "msp430c1331",0,0 },
145 { "msp430c1351",0,0 },
146 { "msp430c311s",0,0 },
147 { "msp430c312",0,0 },
148 { "msp430c313",0,0 },
149 { "msp430c314",0,0 },
150 { "msp430c315",0,0 },
151 { "msp430c323",0,0 },
152 { "msp430c325",0,0 },
153 { "msp430c336",0,1 },
154 { "msp430c337",0,1 },
155 { "msp430c412",0,0 },
156 { "msp430c413",0,0 },
157 { "msp430cg4616",1,1 },
158 { "msp430cg4617",1,1 },
159 { "msp430cg4618",1,1 },
160 { "msp430cg4619",1,1 },
161 { "msp430e112",0,0 },
162 { "msp430e313",0,0 },
163 { "msp430e315",0,0 },
164 { "msp430e325",0,0 },
165 { "msp430e337",0,1 },
166 { "msp430f110",0,0 },
167 { "msp430f1101",0,0 },
168 { "msp430f1101a",0,0 },
169 { "msp430f1111",0,0 },
170 { "msp430f1111a",0,0 },
171 { "msp430f112",0,0 },
172 { "msp430f1121",0,0 },
173 { "msp430f1121a",0,0 },
174 { "msp430f1122",0,0 },
175 { "msp430f1132",0,0 },
176 { "msp430f122",0,0 },
177 { "msp430f1222",0,0 },
178 { "msp430f123",0,0 },
179 { "msp430f1232",0,0 },
180 { "msp430f133",0,0 },
181 { "msp430f135",0,0 },
182 { "msp430f147",0,1 },
183 { "msp430f1471",0,1 },
184 { "msp430f148",0,1 },
185 { "msp430f1481",0,1 },
186 { "msp430f149",0,1 },
187 { "msp430f1491",0,1 },
188 { "msp430f155",0,0 },
189 { "msp430f156",0,0 },
190 { "msp430f157",0,0 },
191 { "msp430f1610",0,1 },
192 { "msp430f1611",0,1 },
193 { "msp430f1612",0,1 },
194 { "msp430f167",0,1 },
195 { "msp430f168",0,1 },
196 { "msp430f169",0,1 },
197 { "msp430f2001",0,0 },
198 { "msp430f2002",0,0 },
199 { "msp430f2003",0,0 },
200 { "msp430f2011",0,0 },
201 { "msp430f2012",0,0 },
202 { "msp430f2013",0,0 },
203 { "msp430f2101",0,0 },
204 { "msp430f2111",0,0 },
205 { "msp430f2112",0,0 },
206 { "msp430f2121",0,0 },
207 { "msp430f2122",0,0 },
208 { "msp430f2131",0,0 },
209 { "msp430f2132",0,0 },
210 { "msp430f2232",0,0 },
211 { "msp430f2234",0,0 },
212 { "msp430f2252",0,0 },
213 { "msp430f2254",0,0 },
214 { "msp430f2272",0,0 },
215 { "msp430f2274",0,0 },
216 { "msp430f233",0,2 },
217 { "msp430f2330",0,2 },
218 { "msp430f235",0,2 },
219 { "msp430f2350",0,2 },
220 { "msp430f2370",0,2 },
221 { "msp430f2410",0,2 },
222 { "msp430f2416",1,2 },
223 { "msp430f2417",1,2 },
224 { "msp430f2418",1,2 },
225 { "msp430f2419",1,2 },
226 { "msp430f247",0,2 },
227 { "msp430f2471",0,2 },
228 { "msp430f248",0,2 },
229 { "msp430f2481",0,2 },
230 { "msp430f249",0,2 },
231 { "msp430f2491",0,2 },
232 { "msp430f2616",1,2 },
233 { "msp430f2617",1,2 },
234 { "msp430f2618",1,2 },
235 { "msp430f2619",1,2 },
236 { "msp430f412",0,0 },
237 { "msp430f413",0,0 },
238 { "msp430f4132",0,0 },
239 { "msp430f415",0,0 },
240 { "msp430f4152",0,0 },
241 { "msp430f417",0,0 },
242 { "msp430f423",0,1 },
243 { "msp430f423a",0,1 },
244 { "msp430f425",0,1 },
245 { "msp430f4250",0,0 },
246 { "msp430f425a",0,1 },
247 { "msp430f4260",0,0 },
248 { "msp430f427",0,1 },
249 { "msp430f4270",0,0 },
250 { "msp430f427a",0,1 },
251 { "msp430f435",0,0 },
252 { "msp430f4351",0,0 },
253 { "msp430f436",0,0 },
254 { "msp430f4361",0,0 },
255 { "msp430f437",0,0 },
256 { "msp430f4371",0,0 },
257 { "msp430f438",0,0 },
258 { "msp430f439",0,0 },
259 { "msp430f447",0,1 },
260 { "msp430f448",0,1 },
261 { "msp430f4481",0,1 },
262 { "msp430f449",0,1 },
263 { "msp430f4491",0,1 },
264 { "msp430f4616",1,1 },
265 { "msp430f46161",1,1 },
266 { "msp430f4617",1,1 },
267 { "msp430f46171",1,1 },
268 { "msp430f4618",1,1 },
269 { "msp430f46181",1,1 },
270 { "msp430f4619",1,1 },
271 { "msp430f46191",1,1 },
272 { "msp430f47126",1,4 },
273 { "msp430f47127",1,4 },
274 { "msp430f47163",1,4 },
275 { "msp430f47166",1,4 },
276 { "msp430f47167",1,4 },
277 { "msp430f47173",1,4 },
278 { "msp430f47176",1,4 },
279 { "msp430f47177",1,4 },
280 { "msp430f47183",1,4 },
281 { "msp430f47186",1,4 },
282 { "msp430f47187",1,4 },
283 { "msp430f47193",1,4 },
284 { "msp430f47196",1,4 },
285 { "msp430f47197",1,4 },
286 { "msp430f477",0,0 },
287 { "msp430f478",0,0 },
288 { "msp430f4783",0,4 },
289 { "msp430f4784",0,4 },
290 { "msp430f479",0,0 },
291 { "msp430f4793",0,4 },
292 { "msp430f4794",0,4 },
293 { "msp430f5131",2,8 },
294 { "msp430f5132",2,8 },
295 { "msp430f5151",2,8 },
296 { "msp430f5152",2,8 },
297 { "msp430f5171",2,8 },
298 { "msp430f5172",2,8 },
299 { "msp430f5212",2,8 },
300 { "msp430f5213",2,8 },
301 { "msp430f5214",2,8 },
302 { "msp430f5217",2,8 },
303 { "msp430f5218",2,8 },
304 { "msp430f5219",2,8 },
305 { "msp430f5222",2,8 },
306 { "msp430f5223",2,8 },
307 { "msp430f5224",2,8 },
308 { "msp430f5227",2,8 },
309 { "msp430f5228",2,8 },
310 { "msp430f5229",2,8 },
311 { "msp430f5232",2,8 },
312 { "msp430f5234",2,8 },
313 { "msp430f5237",2,8 },
314 { "msp430f5239",2,8 },
315 { "msp430f5242",2,8 },
316 { "msp430f5244",2,8 },
317 { "msp430f5247",2,8 },
318 { "msp430f5249",2,8 },
319 { "msp430f5252",2,8 },
320 { "msp430f5253",2,8 },
321 { "msp430f5254",2,8 },
322 { "msp430f5255",2,8 },
323 { "msp430f5256",2,8 },
324 { "msp430f5257",2,8 },
325 { "msp430f5258",2,8 },
326 { "msp430f5259",2,8 },
327 { "msp430f5304",2,8 },
328 { "msp430f5308",2,8 },
329 { "msp430f5309",2,8 },
330 { "msp430f5310",2,8 },
331 { "msp430f5324",2,8 },
332 { "msp430f5325",2,8 },
333 { "msp430f5326",2,8 },
334 { "msp430f5327",2,8 },
335 { "msp430f5328",2,8 },
336 { "msp430f5329",2,8 },
337 { "msp430f5333",2,8 },
338 { "msp430f5335",2,8 },
339 { "msp430f5336",2,8 },
340 { "msp430f5338",2,8 },
341 { "msp430f5340",2,8 },
342 { "msp430f5341",2,8 },
343 { "msp430f5342",2,8 },
344 { "msp430f5358",2,8 },
345 { "msp430f5359",2,8 },
346 { "msp430f5418",2,8 },
347 { "msp430f5418a",2,8 },
348 { "msp430f5419",2,8 },
349 { "msp430f5419a",2,8 },
350 { "msp430f5435",2,8 },
351 { "msp430f5435a",2,8 },
352 { "msp430f5436",2,8 },
353 { "msp430f5436a",2,8 },
354 { "msp430f5437",2,8 },
355 { "msp430f5437a",2,8 },
356 { "msp430f5438",2,8 },
357 { "msp430f5438a",2,8 },
358 { "msp430f5500",2,8 },
359 { "msp430f5501",2,8 },
360 { "msp430f5502",2,8 },
361 { "msp430f5503",2,8 },
362 { "msp430f5504",2,8 },
363 { "msp430f5505",2,8 },
364 { "msp430f5506",2,8 },
365 { "msp430f5507",2,8 },
366 { "msp430f5508",2,8 },
367 { "msp430f5509",2,8 },
368 { "msp430f5510",2,8 },
369 { "msp430f5513",2,8 },
370 { "msp430f5514",2,8 },
371 { "msp430f5515",2,8 },
372 { "msp430f5517",2,8 },
373 { "msp430f5519",2,8 },
374 { "msp430f5521",2,8 },
375 { "msp430f5522",2,8 },
376 { "msp430f5524",2,8 },
377 { "msp430f5525",2,8 },
378 { "msp430f5526",2,8 },
379 { "msp430f5527",2,8 },
380 { "msp430f5528",2,8 },
381 { "msp430f5529",2,8 },
382 { "msp430f5630",2,8 },
383 { "msp430f5631",2,8 },
384 { "msp430f5632",2,8 },
385 { "msp430f5633",2,8 },
386 { "msp430f5634",2,8 },
387 { "msp430f5635",2,8 },
388 { "msp430f5636",2,8 },
389 { "msp430f5637",2,8 },
390 { "msp430f5638",2,8 },
391 { "msp430f5658",2,8 },
392 { "msp430f5659",2,8 },
393 { "msp430f5xx_6xxgeneric",2,8 },
394 { "msp430f6433",2,8 },
395 { "msp430f6435",2,8 },
396 { "msp430f6436",2,8 },
397 { "msp430f6438",2,8 },
398 { "msp430f6458",2,8 },
399 { "msp430f6459",2,8 },
400 { "msp430f6630",2,8 },
401 { "msp430f6631",2,8 },
402 { "msp430f6632",2,8 },
403 { "msp430f6633",2,8 },
404 { "msp430f6634",2,8 },
405 { "msp430f6635",2,8 },
406 { "msp430f6636",2,8 },
407 { "msp430f6637",2,8 },
408 { "msp430f6638",2,8 },
409 { "msp430f6658",2,8 },
410 { "msp430f6659",2,8 },
411 { "msp430f6720",2,8 },
412 { "msp430f6720a",2,8 },
413 { "msp430f6721",2,8 },
414 { "msp430f6721a",2,8 },
415 { "msp430f6723",2,8 },
416 { "msp430f6723a",2,8 },
417 { "msp430f6724",2,8 },
418 { "msp430f6724a",2,8 },
419 { "msp430f6725",2,8 },
420 { "msp430f6725a",2,8 },
421 { "msp430f6726",2,8 },
422 { "msp430f6726a",2,8 },
423 { "msp430f6730",2,8 },
424 { "msp430f6730a",2,8 },
425 { "msp430f6731",2,8 },
426 { "msp430f6731a",2,8 },
427 { "msp430f6733",2,8 },
428 { "msp430f6733a",2,8 },
429 { "msp430f6734",2,8 },
430 { "msp430f6734a",2,8 },
431 { "msp430f6735",2,8 },
432 { "msp430f6735a",2,8 },
433 { "msp430f6736",2,8 },
434 { "msp430f6736a",2,8 },
435 { "msp430f6745",2,8 },
436 { "msp430f67451",2,8 },
437 { "msp430f67451a",2,8 },
438 { "msp430f6745a",2,8 },
439 { "msp430f6746",2,8 },
440 { "msp430f67461",2,8 },
441 { "msp430f67461a",2,8 },
442 { "msp430f6746a",2,8 },
443 { "msp430f6747",2,8 },
444 { "msp430f67471",2,8 },
445 { "msp430f67471a",2,8 },
446 { "msp430f6747a",2,8 },
447 { "msp430f6748",2,8 },
448 { "msp430f67481",2,8 },
449 { "msp430f67481a",2,8 },
450 { "msp430f6748a",2,8 },
451 { "msp430f6749",2,8 },
452 { "msp430f67491",2,8 },
453 { "msp430f67491a",2,8 },
454 { "msp430f6749a",2,8 },
455 { "msp430f67621",2,8 },
456 { "msp430f67621a",2,8 },
457 { "msp430f67641",2,8 },
458 { "msp430f67641a",2,8 },
459 { "msp430f6765",2,8 },
460 { "msp430f67651",2,8 },
461 { "msp430f67651a",2,8 },
462 { "msp430f6765a",2,8 },
463 { "msp430f6766",2,8 },
464 { "msp430f67661",2,8 },
465 { "msp430f67661a",2,8 },
466 { "msp430f6766a",2,8 },
467 { "msp430f6767",2,8 },
468 { "msp430f67671",2,8 },
469 { "msp430f67671a",2,8 },
470 { "msp430f6767a",2,8 },
471 { "msp430f6768",2,8 },
472 { "msp430f67681",2,8 },
473 { "msp430f67681a",2,8 },
474 { "msp430f6768a",2,8 },
475 { "msp430f6769",2,8 },
476 { "msp430f67691",2,8 },
477 { "msp430f67691a",2,8 },
478 { "msp430f6769a",2,8 },
479 { "msp430f6775",2,8 },
480 { "msp430f67751",2,8 },
481 { "msp430f67751a",2,8 },
482 { "msp430f6775a",2,8 },
483 { "msp430f6776",2,8 },
484 { "msp430f67761",2,8 },
485 { "msp430f67761a",2,8 },
486 { "msp430f6776a",2,8 },
487 { "msp430f6777",2,8 },
488 { "msp430f67771",2,8 },
489 { "msp430f67771a",2,8 },
490 { "msp430f6777a",2,8 },
491 { "msp430f6778",2,8 },
492 { "msp430f67781",2,8 },
493 { "msp430f67781a",2,8 },
494 { "msp430f6778a",2,8 },
495 { "msp430f6779",2,8 },
496 { "msp430f67791",2,8 },
497 { "msp430f67791a",2,8 },
498 { "msp430f6779a",2,8 },
499 { "msp430fe423",0,0 },
500 { "msp430fe4232",0,0 },
501 { "msp430fe423a",0,0 },
502 { "msp430fe4242",0,0 },
503 { "msp430fe425",0,0 },
504 { "msp430fe4252",0,0 },
505 { "msp430fe425a",0,0 },
506 { "msp430fe427",0,0 },
507 { "msp430fe4272",0,0 },
508 { "msp430fe427a",0,0 },
509 { "msp430fg4250",0,0 },
510 { "msp430fg4260",0,0 },
511 { "msp430fg4270",0,0 },
512 { "msp430fg437",0,0 },
513 { "msp430fg438",0,0 },
514 { "msp430fg439",0,0 },
515 { "msp430fg4616",1,1 },
516 { "msp430fg4617",1,1 },
517 { "msp430fg4618",1,1 },
518 { "msp430fg4619",1,1 },
519 { "msp430fg477",0,0 },
520 { "msp430fg478",0,0 },
521 { "msp430fg479",0,0 },
522 { "msp430fg6425",2,8 },
523 { "msp430fg6426",2,8 },
524 { "msp430fg6625",2,8 },
525 { "msp430fg6626",2,8 },
526 { "msp430fr2032",2,0 },
527 { "msp430fr2033",2,0 },
528 { "msp430fr2110",2,0 },
529 { "msp430fr2111",2,0 },
530 { "msp430fr2310",2,0 },
531 { "msp430fr2311",2,0 },
532 { "msp430fr2433",2,8 },
533 { "msp430fr2532",2,8 },
534 { "msp430fr2533",2,8 },
535 { "msp430fr2632",2,8 },
536 { "msp430fr2633",2,8 },
537 { "msp430fr2xx_4xxgeneric",2,8 },
538 { "msp430fr4131",2,0 },
539 { "msp430fr4132",2,0 },
540 { "msp430fr4133",2,0 },
541 { "msp430fr5720",2,8 },
542 { "msp430fr5721",2,8 },
543 { "msp430fr5722",2,8 },
544 { "msp430fr5723",2,8 },
545 { "msp430fr5724",2,8 },
546 { "msp430fr5725",2,8 },
547 { "msp430fr5726",2,8 },
548 { "msp430fr5727",2,8 },
549 { "msp430fr5728",2,8 },
550 { "msp430fr5729",2,8 },
551 { "msp430fr5730",2,8 },
552 { "msp430fr5731",2,8 },
553 { "msp430fr5732",2,8 },
554 { "msp430fr5733",2,8 },
555 { "msp430fr5734",2,8 },
556 { "msp430fr5735",2,8 },
557 { "msp430fr5736",2,8 },
558 { "msp430fr5737",2,8 },
559 { "msp430fr5738",2,8 },
560 { "msp430fr5739",2,8 },
561 { "msp430fr57xxgeneric",2,8 },
562 { "msp430fr5847",2,8 },
563 { "msp430fr58471",2,8 },
564 { "msp430fr5848",2,8 },
565 { "msp430fr5849",2,8 },
566 { "msp430fr5857",2,8 },
567 { "msp430fr5858",2,8 },
568 { "msp430fr5859",2,8 },
569 { "msp430fr5867",2,8 },
570 { "msp430fr58671",2,8 },
571 { "msp430fr5868",2,8 },
572 { "msp430fr5869",2,8 },
573 { "msp430fr5870",2,8 },
574 { "msp430fr5872",2,8 },
575 { "msp430fr58721",2,8 },
576 { "msp430fr5887",2,8 },
577 { "msp430fr5888",2,8 },
578 { "msp430fr5889",2,8 },
579 { "msp430fr58891",2,8 },
580 { "msp430fr5922",2,8 },
581 { "msp430fr59221",2,8 },
582 { "msp430fr5947",2,8 },
583 { "msp430fr59471",2,8 },
584 { "msp430fr5948",2,8 },
585 { "msp430fr5949",2,8 },
586 { "msp430fr5957",2,8 },
587 { "msp430fr5958",2,8 },
588 { "msp430fr5959",2,8 },
589 { "msp430fr5962",2,8 },
590 { "msp430fr5964",2,8 },
591 { "msp430fr5967",2,8 },
592 { "msp430fr5968",2,8 },
593 { "msp430fr5969",2,8 },
594 { "msp430fr59691",2,8 },
595 { "msp430fr5970",2,8 },
596 { "msp430fr5972",2,8 },
597 { "msp430fr59721",2,8 },
598 { "msp430fr5986",2,8 },
599 { "msp430fr5987",2,8 },
600 { "msp430fr5988",2,8 },
601 { "msp430fr5989",2,8 },
602 { "msp430fr59891",2,8 },
603 { "msp430fr5992",2,8 },
604 { "msp430fr5994",2,8 },
605 { "msp430fr59941",2,8 },
606 { "msp430fr5xx_6xxgeneric",2,8 },
607 { "msp430fr6820",2,8 },
608 { "msp430fr6822",2,8 },
609 { "msp430fr68221",2,8 },
610 { "msp430fr6870",2,8 },
611 { "msp430fr6872",2,8 },
612 { "msp430fr68721",2,8 },
613 { "msp430fr6877",2,8 },
614 { "msp430fr6879",2,8 },
615 { "msp430fr68791",2,8 },
616 { "msp430fr6887",2,8 },
617 { "msp430fr6888",2,8 },
618 { "msp430fr6889",2,8 },
619 { "msp430fr68891",2,8 },
620 { "msp430fr6920",2,8 },
621 { "msp430fr6922",2,8 },
622 { "msp430fr69221",2,8 },
623 { "msp430fr6927",2,8 },
624 { "msp430fr69271",2,8 },
625 { "msp430fr6928",2,8 },
626 { "msp430fr6970",2,8 },
627 { "msp430fr6972",2,8 },
628 { "msp430fr69721",2,8 },
629 { "msp430fr6977",2,8 },
630 { "msp430fr6979",2,8 },
631 { "msp430fr69791",2,8 },
632 { "msp430fr6987",2,8 },
633 { "msp430fr6988",2,8 },
634 { "msp430fr6989",2,8 },
635 { "msp430fr69891",2,8 },
636 { "msp430fw423",0,0 },
637 { "msp430fw425",0,0 },
638 { "msp430fw427",0,0 },
639 { "msp430fw428",0,0 },
640 { "msp430fw429",0,0 },
641 { "msp430g2001",0,0 },
642 { "msp430g2101",0,0 },
643 { "msp430g2102",0,0 },
644 { "msp430g2111",0,0 },
645 { "msp430g2112",0,0 },
646 { "msp430g2113",0,0 },
647 { "msp430g2121",0,0 },
648 { "msp430g2131",0,0 },
649 { "msp430g2132",0,0 },
650 { "msp430g2152",0,0 },
651 { "msp430g2153",0,0 },
652 { "msp430g2201",0,0 },
653 { "msp430g2202",0,0 },
654 { "msp430g2203",0,0 },
655 { "msp430g2210",0,0 },
656 { "msp430g2211",0,0 },
657 { "msp430g2212",0,0 },
658 { "msp430g2213",0,0 },
659 { "msp430g2221",0,0 },
660 { "msp430g2230",0,0 },
661 { "msp430g2231",0,0 },
662 { "msp430g2232",0,0 },
663 { "msp430g2233",0,0 },
664 { "msp430g2252",0,0 },
665 { "msp430g2253",0,0 },
666 { "msp430g2302",0,0 },
667 { "msp430g2303",0,0 },
668 { "msp430g2312",0,0 },
669 { "msp430g2313",0,0 },
670 { "msp430g2332",0,0 },
671 { "msp430g2333",0,0 },
672 { "msp430g2352",0,0 },
673 { "msp430g2353",0,0 },
674 { "msp430g2402",0,0 },
675 { "msp430g2403",0,0 },
676 { "msp430g2412",0,0 },
677 { "msp430g2413",0,0 },
678 { "msp430g2432",0,0 },
679 { "msp430g2433",0,0 },
680 { "msp430g2444",0,0 },
681 { "msp430g2452",0,0 },
682 { "msp430g2453",0,0 },
683 { "msp430g2513",0,0 },
684 { "msp430g2533",0,0 },
685 { "msp430g2544",0,0 },
686 { "msp430g2553",0,0 },
687 { "msp430g2744",0,0 },
688 { "msp430g2755",0,0 },
689 { "msp430g2855",0,0 },
690 { "msp430g2955",0,0 },
691 { "msp430i2020",0,2 },
692 { "msp430i2021",0,2 },
693 { "msp430i2030",0,2 },
694 { "msp430i2031",0,2 },
695 { "msp430i2040",0,2 },
696 { "msp430i2041",0,2 },
697 { "msp430i2xxgeneric",0,2 },
698 { "msp430l092",0,0 },
699 { "msp430p112",0,0 },
700 { "msp430p313",0,0 },
701 { "msp430p315",0,0 },
702 { "msp430p315s",0,0 },
703 { "msp430p325",0,0 },
704 { "msp430p337",0,1 },
705 { "msp430sl5438a",2,8 },
706 { "msp430tch5e",0,0 },
707 { "msp430xgeneric",2,8 },
708 { "rf430f5144",2,8 },
709 { "rf430f5155",2,8 },
710 { "rf430f5175",2,8 },
711 { "rf430frl152h",0,0 },
712 { "rf430frl152h_rom",0,0 },
713 { "rf430frl153h",0,0 },
714 { "rf430frl153h_rom",0,0 },
715 { "rf430frl154h",0,0 },
716 { "rf430frl154h_rom",0,0 }
719 /* Generate a C preprocessor symbol based upon the MCU selected by the user.
720 If a specific MCU has not been selected then return a generic symbol instead. */
722 const char *
723 msp430_mcu_name (void)
725 if (target_mcu)
727 unsigned int i;
728 static char mcu_name [64];
730 snprintf (mcu_name, sizeof (mcu_name) - 1, "__%s__", target_mcu);
731 for (i = strlen (mcu_name); i--;)
732 mcu_name[i] = TOUPPER (mcu_name[i]);
733 return mcu_name;
736 return msp430x ? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
739 static const char *
740 hwmult_name (unsigned int val)
742 switch (val)
744 case 0: return "none";
745 case 1: return "16-bit";
746 case 2: return "16-bit";
747 case 4: return "32-bit";
748 case 8: return "32-bit (5xx)";
749 default: gcc_unreachable ();
753 static void
754 msp430_option_override (void)
756 /* The MSP430 architecture can safely dereference a NULL pointer. In fact,
757 there are memory mapped registers there. */
758 flag_delete_null_pointer_checks = 0;
760 init_machine_status = msp430_init_machine_status;
762 if (target_cpu)
764 /* gcc/common/config/msp430-common.c will have
765 already canonicalised the string in target_cpu. */
766 if (strcasecmp (target_cpu, "msp430x") == 0)
767 msp430x = true;
768 else /* target_cpu == "msp430" - already handled by the front end. */
769 msp430x = false;
772 if (target_mcu)
774 int i;
776 /* FIXME: If the array were alpha sorted, we could use a binary search. */
777 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
778 if (strcasecmp (msp430_mcu_data[i].name, target_mcu) == 0)
780 bool xisa = msp430_mcu_data[i].revision >= 1;
782 if (msp430_warn_mcu)
784 if (target_cpu&& msp430x != xisa)
785 warning (0, "MCU '%s' supports %s ISA but -mcpu option is set to %s",
786 target_mcu, xisa ? "430X" : "430", msp430x ? "430X" : "430");
788 if (msp430_mcu_data[i].hwmpy == 0
789 && msp430_hwmult_type != MSP430_HWMULT_AUTO
790 && msp430_hwmult_type != MSP430_HWMULT_NONE)
791 warning (0, "MCU '%s' does not have hardware multiply support, but -mhwmult is set to %s",
792 target_mcu,
793 msp430_hwmult_type == MSP430_HWMULT_SMALL ? "16-bit"
794 : msp430_hwmult_type == MSP430_HWMULT_LARGE ? "32-bit" : "f5series");
795 else if (msp430_hwmult_type == MSP430_HWMULT_SMALL
796 && msp430_mcu_data[i].hwmpy != 1
797 && msp430_mcu_data[i].hwmpy != 2 )
798 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to 16-bit",
799 target_mcu, hwmult_name (msp430_mcu_data[i].hwmpy));
800 else if (msp430_hwmult_type == MSP430_HWMULT_LARGE && msp430_mcu_data[i].hwmpy != 4)
801 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to 32-bit",
802 target_mcu, hwmult_name (msp430_mcu_data[i].hwmpy));
803 else if (msp430_hwmult_type == MSP430_HWMULT_F5SERIES && msp430_mcu_data[i].hwmpy != 8)
804 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to f5series",
805 target_mcu, hwmult_name (msp430_mcu_data[i].hwmpy));
808 msp430x = xisa;
809 break;
812 if (i < 0)
814 if (msp430_hwmult_type == MSP430_HWMULT_AUTO)
816 if (msp430_warn_mcu)
818 if (target_cpu == NULL)
819 warning (0,
820 "Unrecognized MCU name '%s', assuming that it is "
821 "just a MSP430 with no hardware multiply.\n"
822 "Use the -mcpu and -mhwmult options to set "
823 "these explicitly.",
824 target_mcu);
825 else
826 warning (0,
827 "Unrecognized MCU name '%s', assuming that it "
828 "has no hardware multiply.\nUse the -mhwmult "
829 "option to set this explicitly.",
830 target_mcu);
833 msp430_hwmult_type = MSP430_HWMULT_NONE;
835 else if (target_cpu == NULL)
837 if (msp430_warn_mcu)
838 warning (0,
839 "Unrecognized MCU name '%s', assuming that it just "
840 "supports the MSP430 ISA.\nUse the -mcpu option to "
841 "set the ISA explicitly.",
842 target_mcu);
844 msp430x = false;
846 else if (msp430_warn_mcu)
847 warning (0, "Unrecognized MCU name '%s'.", target_mcu);
851 /* The F5 series are all able to support the 430X ISA. */
852 if (target_cpu == NULL && target_mcu == NULL && msp430_hwmult_type == MSP430_HWMULT_F5SERIES)
853 msp430x = true;
855 if (TARGET_LARGE && !msp430x)
856 error ("-mlarge requires a 430X-compatible -mmcu=");
858 if (msp430_code_region == MSP430_REGION_UPPER && ! msp430x)
859 error ("-mcode-region=upper requires 430X-compatible cpu");
860 if (msp430_data_region == MSP430_REGION_UPPER && ! msp430x)
861 error ("-mdata-region=upper requires 430X-compatible cpu");
863 if (flag_exceptions || flag_non_call_exceptions
864 || flag_unwind_tables || flag_asynchronous_unwind_tables)
865 flag_omit_frame_pointer = false;
866 else
867 flag_omit_frame_pointer = true;
869 /* This is a hack to work around a problem with the newlib build
870 mechanism. Newlib always appends CFLAGS to the end of the GCC
871 command line and always sets -O2 in CFLAGS. Thus it is not
872 possible to build newlib with -Os enabled. Until now... */
873 if (TARGET_OPT_SPACE && optimize < 3)
874 optimize_size = 1;
877 #undef TARGET_SCALAR_MODE_SUPPORTED_P
878 #define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
880 static bool
881 msp430_scalar_mode_supported_p (scalar_mode m)
883 if (m == PSImode && msp430x)
884 return true;
885 #if 0
886 if (m == TImode)
887 return true;
888 #endif
889 return default_scalar_mode_supported_p (m);
894 /* Storage Layout */
896 #undef TARGET_MS_BITFIELD_LAYOUT_P
897 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
899 bool
900 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED)
902 return false;
907 /* Register Usage */
909 #undef TARGET_HARD_REGNO_NREGS
910 #define TARGET_HARD_REGNO_NREGS msp430_hard_regno_nregs
912 static unsigned int
913 msp430_hard_regno_nregs (unsigned int, machine_mode mode)
915 if (mode == PSImode && msp430x)
916 return 1;
917 if (mode == CPSImode && msp430x)
918 return 2;
919 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
920 / UNITS_PER_WORD);
923 /* Implements HARD_REGNO_NREGS_HAS_PADDING. */
925 msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED,
926 machine_mode mode)
928 if (mode == PSImode && msp430x)
929 return 1;
930 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
931 / UNITS_PER_WORD);
934 /* Implements HARD_REGNO_NREGS_WITH_PADDING. */
936 msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED,
937 machine_mode mode)
939 if (mode == PSImode)
940 return 2;
941 if (mode == CPSImode)
942 return 4;
943 return msp430_hard_regno_nregs (regno, mode);
946 #undef TARGET_HARD_REGNO_MODE_OK
947 #define TARGET_HARD_REGNO_MODE_OK msp430_hard_regno_mode_ok
949 static bool
950 msp430_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
952 return regno <= (ARG_POINTER_REGNUM
953 - (unsigned int) msp430_hard_regno_nregs (regno, mode));
956 #undef TARGET_MODES_TIEABLE_P
957 #define TARGET_MODES_TIEABLE_P msp430_modes_tieable_p
959 static bool
960 msp430_modes_tieable_p (machine_mode mode1, machine_mode mode2)
962 if ((mode1 == PSImode || mode2 == SImode)
963 || (mode1 == SImode || mode2 == PSImode))
964 return false;
966 return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
967 || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
968 == (GET_MODE_CLASS (mode2) == MODE_FLOAT
969 || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
972 #undef TARGET_FRAME_POINTER_REQUIRED
973 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
975 static bool
976 msp430_frame_pointer_required (void)
978 return false;
981 #undef TARGET_CAN_ELIMINATE
982 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
984 static bool
985 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED,
986 const int to_reg ATTRIBUTE_UNUSED)
988 return true;
991 /* Implements INITIAL_ELIMINATION_OFFSET. */
993 msp430_initial_elimination_offset (int from, int to)
995 int rv = 0; /* As if arg to arg. */
997 msp430_compute_frame_info ();
999 switch (to)
1001 case STACK_POINTER_REGNUM:
1002 rv += cfun->machine->framesize_outgoing;
1003 rv += cfun->machine->framesize_locals;
1004 /* Fall through. */
1005 case FRAME_POINTER_REGNUM:
1006 rv += cfun->machine->framesize_regs;
1007 /* Allow for the saved return address. */
1008 rv += (TARGET_LARGE ? 4 : 2);
1009 /* NB/ No need to allow for crtl->args.pretend_args_size.
1010 GCC does that for us. */
1011 break;
1012 default:
1013 gcc_unreachable ();
1016 switch (from)
1018 case FRAME_POINTER_REGNUM:
1019 /* Allow for the fall through above. */
1020 rv -= (TARGET_LARGE ? 4 : 2);
1021 rv -= cfun->machine->framesize_regs;
1022 case ARG_POINTER_REGNUM:
1023 break;
1024 default:
1025 gcc_unreachable ();
1028 return rv;
1031 /* Named Address Space support */
1034 /* Return the appropriate mode for a named address pointer. */
1035 #undef TARGET_ADDR_SPACE_POINTER_MODE
1036 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
1037 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
1038 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
1040 static scalar_int_mode
1041 msp430_addr_space_pointer_mode (addr_space_t addrspace)
1043 switch (addrspace)
1045 default:
1046 case ADDR_SPACE_GENERIC:
1047 return Pmode;
1048 case ADDR_SPACE_NEAR:
1049 return HImode;
1050 case ADDR_SPACE_FAR:
1051 return PSImode;
1055 /* Function pointers are stored in unwind_word sized
1056 variables, so make sure that unwind_word is big enough. */
1057 #undef TARGET_UNWIND_WORD_MODE
1058 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
1060 static scalar_int_mode
1061 msp430_unwind_word_mode (void)
1063 /* This needs to match msp430_init_dwarf_reg_sizes_extra (below). */
1064 return msp430x ? PSImode : HImode;
1067 /* Determine if one named address space is a subset of another. */
1068 #undef TARGET_ADDR_SPACE_SUBSET_P
1069 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
1070 static bool
1071 msp430_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
1073 if (subset == superset)
1074 return true;
1075 else
1076 return (subset != ADDR_SPACE_FAR && superset == ADDR_SPACE_FAR);
1079 #undef TARGET_ADDR_SPACE_CONVERT
1080 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
1081 /* Convert from one address space to another. */
1082 static rtx
1083 msp430_addr_space_convert (rtx op, tree from_type, tree to_type)
1085 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
1086 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
1087 rtx result;
1089 if (to_as != ADDR_SPACE_FAR && from_as == ADDR_SPACE_FAR)
1091 /* This is unpredictable, as we're truncating off usable address
1092 bits. */
1094 if (CONSTANT_P (op))
1095 return gen_rtx_CONST (HImode, op);
1097 result = gen_reg_rtx (HImode);
1098 emit_insn (gen_truncpsihi2 (result, op));
1099 return result;
1101 else if (to_as == ADDR_SPACE_FAR && from_as != ADDR_SPACE_FAR)
1103 /* This always works. */
1105 if (CONSTANT_P (op))
1106 return gen_rtx_CONST (PSImode, op);
1108 result = gen_reg_rtx (PSImode);
1109 emit_insn (gen_zero_extendhipsi2 (result, op));
1110 return result;
1112 else
1113 gcc_unreachable ();
1116 /* Stack Layout and Calling Conventions. */
1118 /* For each function, we list the gcc version and the TI version on
1119 each line, where we're converting the function names. */
1120 static char const * const special_convention_function_names [] =
1122 "__muldi3", "__mspabi_mpyll",
1123 "__udivdi3", "__mspabi_divull",
1124 "__umoddi3", "__mspabi_remull",
1125 "__divdi3", "__mspabi_divlli",
1126 "__moddi3", "__mspabi_remlli",
1127 "__mspabi_srall",
1128 "__mspabi_srlll",
1129 "__mspabi_sllll",
1130 "__adddf3", "__mspabi_addd",
1131 "__subdf3", "__mspabi_subd",
1132 "__muldf3", "__mspabi_mpyd",
1133 "__divdf3", "__mspabi_divd",
1134 "__mspabi_cmpd",
1135 NULL
1138 /* TRUE if the function passed is a "speical" function. Special
1139 functions pass two DImode parameters in registers. */
1140 static bool
1141 msp430_special_register_convention_p (const char *name)
1143 int i;
1145 for (i = 0; special_convention_function_names [i]; i++)
1146 if (! strcmp (name, special_convention_function_names [i]))
1147 return true;
1149 return false;
1152 #undef TARGET_FUNCTION_VALUE_REGNO_P
1153 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
1155 bool
1156 msp430_function_value_regno_p (unsigned int regno)
1158 return regno == 12;
1162 #undef TARGET_FUNCTION_VALUE
1163 #define TARGET_FUNCTION_VALUE msp430_function_value
1166 msp430_function_value (const_tree ret_type,
1167 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1168 bool outgoing ATTRIBUTE_UNUSED)
1170 return gen_rtx_REG (TYPE_MODE (ret_type), 12);
1173 #undef TARGET_LIBCALL_VALUE
1174 #define TARGET_LIBCALL_VALUE msp430_libcall_value
1177 msp430_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
1179 return gen_rtx_REG (mode, 12);
1182 /* Implements INIT_CUMULATIVE_ARGS. */
1183 void
1184 msp430_init_cumulative_args (CUMULATIVE_ARGS *ca,
1185 tree fntype ATTRIBUTE_UNUSED,
1186 rtx libname ATTRIBUTE_UNUSED,
1187 tree fndecl ATTRIBUTE_UNUSED,
1188 int n_named_args ATTRIBUTE_UNUSED)
1190 const char *fname;
1191 memset (ca, 0, sizeof(*ca));
1193 ca->can_split = 1;
1195 if (fndecl)
1196 fname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
1197 else if (libname)
1198 fname = XSTR (libname, 0);
1199 else
1200 fname = NULL;
1202 if (fname && msp430_special_register_convention_p (fname))
1203 ca->special_p = 1;
1206 /* Helper function for argument passing; this function is the common
1207 code that determines where an argument will be passed. */
1208 static void
1209 msp430_evaluate_arg (cumulative_args_t cap,
1210 machine_mode mode,
1211 const_tree type ATTRIBUTE_UNUSED,
1212 bool named)
1214 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1215 int nregs = GET_MODE_SIZE (mode);
1216 int i;
1218 ca->reg_count = 0;
1219 ca->mem_count = 0;
1221 if (!named)
1222 return;
1224 if (mode == PSImode)
1225 nregs = 1;
1226 else
1227 nregs = (nregs + 1) / 2;
1229 if (ca->special_p)
1231 /* Function is passed two DImode operands, in R8:R11 and
1232 R12:15. */
1233 ca->start_reg = 8;
1234 ca->reg_count = 4;
1235 return;
1238 switch (nregs)
1240 case 1:
1241 for (i = 0; i < 4; i++)
1242 if (! ca->reg_used [i])
1244 ca->reg_count = 1;
1245 ca->start_reg = CA_FIRST_REG + i;
1246 return;
1248 break;
1249 case 2:
1250 for (i = 0; i < 3; i++)
1251 if (! ca->reg_used [i] && ! ca->reg_used [i + 1])
1253 ca->reg_count = 2;
1254 ca->start_reg = CA_FIRST_REG + i;
1255 return;
1257 if (! ca->reg_used [3] && ca->can_split)
1259 ca->reg_count = 1;
1260 ca->mem_count = 2;
1261 ca->start_reg = CA_FIRST_REG + 3;
1262 return;
1264 break;
1265 case 3:
1266 case 4:
1267 ca->can_split = 0;
1268 if (! ca->reg_used [0]
1269 && ! ca->reg_used [1]
1270 && ! ca->reg_used [2]
1271 && ! ca->reg_used [3])
1273 ca->reg_count = 4;
1274 ca->start_reg = CA_FIRST_REG;
1275 return;
1277 break;
1281 #undef TARGET_PROMOTE_PROTOTYPES
1282 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
1284 bool
1285 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED)
1287 return false;
1290 #undef TARGET_FUNCTION_ARG
1291 #define TARGET_FUNCTION_ARG msp430_function_arg
1294 msp430_function_arg (cumulative_args_t cap,
1295 machine_mode mode,
1296 const_tree type,
1297 bool named)
1299 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1301 msp430_evaluate_arg (cap, mode, type, named);
1303 if (ca->reg_count)
1304 return gen_rtx_REG (mode, ca->start_reg);
1306 return 0;
1309 #undef TARGET_ARG_PARTIAL_BYTES
1310 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
1313 msp430_arg_partial_bytes (cumulative_args_t cap,
1314 machine_mode mode,
1315 tree type,
1316 bool named)
1318 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1320 msp430_evaluate_arg (cap, mode, type, named);
1322 if (ca->reg_count && ca->mem_count)
1323 return ca->reg_count * UNITS_PER_WORD;
1325 return 0;
1328 #undef TARGET_PASS_BY_REFERENCE
1329 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
1331 static bool
1332 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED,
1333 machine_mode mode,
1334 const_tree type,
1335 bool named ATTRIBUTE_UNUSED)
1337 return (mode == BLKmode
1338 || (type && TREE_CODE (type) == RECORD_TYPE)
1339 || (type && TREE_CODE (type) == UNION_TYPE));
1342 #undef TARGET_CALLEE_COPIES
1343 #define TARGET_CALLEE_COPIES msp430_callee_copies
1345 static bool
1346 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED,
1347 machine_mode mode ATTRIBUTE_UNUSED,
1348 const_tree type ATTRIBUTE_UNUSED,
1349 bool named ATTRIBUTE_UNUSED)
1351 return true;
1354 #undef TARGET_FUNCTION_ARG_ADVANCE
1355 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
1357 void
1358 msp430_function_arg_advance (cumulative_args_t cap,
1359 machine_mode mode,
1360 const_tree type,
1361 bool named)
1363 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1364 int i;
1366 msp430_evaluate_arg (cap, mode, type, named);
1368 if (ca->start_reg >= CA_FIRST_REG)
1369 for (i = 0; i < ca->reg_count; i ++)
1370 ca->reg_used [i + ca->start_reg - CA_FIRST_REG] = 1;
1372 ca->special_p = 0;
1375 #undef TARGET_FUNCTION_ARG_BOUNDARY
1376 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
1378 static unsigned int
1379 msp430_function_arg_boundary (machine_mode mode, const_tree type)
1381 if (mode == BLKmode
1382 && int_size_in_bytes (type) > 1)
1383 return 16;
1384 if (GET_MODE_BITSIZE (mode) > 8)
1385 return 16;
1386 return 8;
1389 #undef TARGET_RETURN_IN_MEMORY
1390 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
1392 static bool
1393 msp430_return_in_memory (const_tree ret_type, const_tree fntype ATTRIBUTE_UNUSED)
1395 machine_mode mode = TYPE_MODE (ret_type);
1397 if (mode == BLKmode
1398 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == RECORD_TYPE)
1399 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == UNION_TYPE))
1400 return true;
1402 if (GET_MODE_SIZE (mode) > 8)
1403 return true;
1405 return false;
1408 #undef TARGET_GET_RAW_ARG_MODE
1409 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
1411 static fixed_size_mode
1412 msp430_get_raw_arg_mode (int regno)
1414 return as_a <fixed_size_mode> (regno == ARG_POINTER_REGNUM
1415 ? VOIDmode : Pmode);
1418 #undef TARGET_GET_RAW_RESULT_MODE
1419 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
1421 static fixed_size_mode
1422 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED)
1424 return Pmode;
1427 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
1428 #define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
1430 #include "gimplify.h"
1432 static tree
1433 msp430_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
1434 gimple_seq *post_p)
1436 tree addr, t, type_size, rounded_size, valist_tmp;
1437 unsigned HOST_WIDE_INT align, boundary;
1438 bool indirect;
1440 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
1441 if (indirect)
1442 type = build_pointer_type (type);
1444 align = PARM_BOUNDARY / BITS_PER_UNIT;
1445 boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
1447 /* When we align parameter on stack for caller, if the parameter
1448 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
1449 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
1450 here with caller. */
1451 if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
1452 boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
1454 boundary /= BITS_PER_UNIT;
1456 /* Hoist the valist value into a temporary for the moment. */
1457 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
1459 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
1460 requires greater alignment, we must perform dynamic alignment. */
1461 if (boundary > align
1462 && !integer_zerop (TYPE_SIZE (type)))
1464 /* FIXME: This is where this function diverts from targhooks.c:
1465 std_gimplify_va_arg_expr(). It works, but I do not know why... */
1466 if (! POINTER_TYPE_P (type))
1468 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
1469 fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
1470 gimplify_and_add (t, pre_p);
1472 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
1473 fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
1474 valist_tmp,
1475 build_int_cst (TREE_TYPE (valist), -boundary)));
1476 gimplify_and_add (t, pre_p);
1479 else
1480 boundary = align;
1482 /* If the actual alignment is less than the alignment of the type,
1483 adjust the type accordingly so that we don't assume strict alignment
1484 when dereferencing the pointer. */
1485 boundary *= BITS_PER_UNIT;
1486 if (boundary < TYPE_ALIGN (type))
1488 type = build_variant_type_copy (type);
1489 SET_TYPE_ALIGN (type, boundary);
1492 /* Compute the rounded size of the type. */
1493 type_size = size_in_bytes (type);
1494 rounded_size = round_up (type_size, align);
1496 /* Reduce rounded_size so it's sharable with the postqueue. */
1497 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
1499 /* Get AP. */
1500 addr = valist_tmp;
1502 /* Compute new value for AP. */
1503 t = fold_build_pointer_plus (valist_tmp, rounded_size);
1504 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
1505 gimplify_and_add (t, pre_p);
1507 addr = fold_convert (build_pointer_type (type), addr);
1509 if (indirect)
1510 addr = build_va_arg_indirect_ref (addr);
1512 addr = build_va_arg_indirect_ref (addr);
1514 return addr;
1517 #undef TARGET_LRA_P
1518 #define TARGET_LRA_P hook_bool_void_false
1520 /* Addressing Modes */
1522 #undef TARGET_LEGITIMATE_ADDRESS_P
1523 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
1525 static bool
1526 reg_ok_for_addr (rtx r, bool strict)
1528 int rn = REGNO (r);
1530 if (strict && rn >= FIRST_PSEUDO_REGISTER)
1531 rn = reg_renumber [rn];
1532 if (strict && 0 <= rn && rn < FIRST_PSEUDO_REGISTER)
1533 return true;
1534 if (!strict)
1535 return true;
1536 return false;
1539 bool
1540 msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
1541 rtx x ATTRIBUTE_UNUSED,
1542 bool strict ATTRIBUTE_UNUSED)
1544 switch (GET_CODE (x))
1546 case MEM:
1547 return false;
1549 case PLUS:
1550 if (REG_P (XEXP (x, 0)))
1552 if (GET_MODE (x) != GET_MODE (XEXP (x, 0)))
1553 return false;
1554 if (!reg_ok_for_addr (XEXP (x, 0), strict))
1555 return false;
1556 switch (GET_CODE (XEXP (x, 1)))
1558 case CONST:
1559 case SYMBOL_REF:
1560 case CONST_INT:
1561 return true;
1562 default:
1563 return false;
1566 return false;
1568 case REG:
1569 if (!reg_ok_for_addr (x, strict))
1570 return false;
1571 /* FALLTHRU */
1572 case CONST:
1573 case SYMBOL_REF:
1574 case CONST_INT:
1575 return true;
1577 default:
1578 return false;
1582 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1583 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
1585 bool
1586 msp430_addr_space_legitimate_address_p (machine_mode mode,
1587 rtx x,
1588 bool strict,
1589 addr_space_t as ATTRIBUTE_UNUSED)
1591 return msp430_legitimate_address_p (mode, x, strict);
1594 #undef TARGET_ASM_INTEGER
1595 #define TARGET_ASM_INTEGER msp430_asm_integer
1596 static bool
1597 msp430_asm_integer (rtx x, unsigned int size, int aligned_p)
1599 int c = GET_CODE (x);
1601 if (size == 3 && GET_MODE (x) == PSImode)
1602 size = 4;
1604 switch (size)
1606 case 4:
1607 if (c == SYMBOL_REF || c == CONST || c == LABEL_REF || c == CONST_INT
1608 || c == PLUS || c == MINUS)
1610 fprintf (asm_out_file, "\t.long\t");
1611 output_addr_const (asm_out_file, x);
1612 fputc ('\n', asm_out_file);
1613 return true;
1615 break;
1617 return default_assemble_integer (x, size, aligned_p);
1620 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
1621 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra
1622 static bool
1623 msp430_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED, rtx x)
1625 debug_rtx(x);
1626 return false;
1629 #undef TARGET_LEGITIMATE_CONSTANT_P
1630 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
1632 static bool
1633 msp430_legitimate_constant (machine_mode mode, rtx x)
1635 return ! CONST_INT_P (x)
1636 || mode != PSImode
1637 /* GCC does not know the width of the PSImode, so make
1638 sure that it does not try to use a constant value that
1639 is out of range. */
1640 || (INTVAL (x) < (1 << 20) && INTVAL (x) >= (HOST_WIDE_INT)(HOST_WIDE_INT_M1U << 20));
1644 #undef TARGET_RTX_COSTS
1645 #define TARGET_RTX_COSTS msp430_rtx_costs
1647 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED,
1648 machine_mode mode,
1649 int outer_code ATTRIBUTE_UNUSED,
1650 int opno ATTRIBUTE_UNUSED,
1651 int * total,
1652 bool speed ATTRIBUTE_UNUSED)
1654 int code = GET_CODE (x);
1656 switch (code)
1658 case SIGN_EXTEND:
1659 if (mode == SImode && outer_code == SET)
1661 *total = COSTS_N_INSNS (4);
1662 return true;
1664 break;
1665 case ASHIFT:
1666 case ASHIFTRT:
1667 case LSHIFTRT:
1668 if (!msp430x)
1670 *total = COSTS_N_INSNS (100);
1671 return true;
1673 break;
1675 return false;
1678 /* Function Entry and Exit */
1680 /* The MSP430 call frame looks like this:
1682 <higher addresses>
1683 +--------------------+
1685 | Stack Arguments |
1687 +--------------------+ <-- "arg pointer"
1689 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
1691 +--------------------+
1692 | SR if this func has|
1693 | been called via an |
1694 | interrupt. |
1695 +--------------------+ <-- SP before prologue, also AP
1697 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
1699 +--------------------+ <-- "frame pointer"
1701 | Locals |
1703 +--------------------+
1705 | Outgoing Args |
1707 +--------------------+ <-- SP during function
1708 <lower addresses>
1712 /* We use this to wrap all emitted insns in the prologue, so they get
1713 the "frame-related" (/f) flag set. */
1714 static rtx
1715 F (rtx x)
1717 RTX_FRAME_RELATED_P (x) = 1;
1718 return x;
1721 /* This is the one spot that decides if a register is to be saved and
1722 restored in the prologue/epilogue. */
1723 static bool
1724 msp430_preserve_reg_p (int regno)
1726 /* PC, SP, SR, and the constant generator. */
1727 if (regno <= 3)
1728 return false;
1730 /* FIXME: add interrupt, EH, etc. */
1731 if (crtl->calls_eh_return)
1732 return true;
1734 /* Shouldn't be more than the above, but just in case... */
1735 if (fixed_regs [regno])
1736 return false;
1738 /* Interrupt handlers save all registers they use, even
1739 ones which are call saved. If they call other functions
1740 then *every* register is saved. */
1741 if (msp430_is_interrupt_func ())
1742 return ! crtl->is_leaf || df_regs_ever_live_p (regno);
1744 if (!call_used_regs [regno]
1745 && df_regs_ever_live_p (regno))
1746 return true;
1748 return false;
1751 /* Compute all the frame-related fields in our machine_function
1752 structure. */
1753 static void
1754 msp430_compute_frame_info (void)
1756 int i;
1758 cfun->machine->computed = 1;
1759 cfun->machine->framesize_regs = 0;
1760 cfun->machine->framesize_locals = get_frame_size ();
1761 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
1763 for (i = 0; i < ARG_POINTER_REGNUM; i ++)
1764 if (msp430_preserve_reg_p (i))
1766 cfun->machine->need_to_save [i] = 1;
1767 cfun->machine->framesize_regs += (TARGET_LARGE ? 4 : 2);
1769 else
1770 cfun->machine->need_to_save [i] = 0;
1772 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
1773 cfun->machine->framesize_locals ++;
1775 cfun->machine->framesize = (cfun->machine->framesize_regs
1776 + cfun->machine->framesize_locals
1777 + cfun->machine->framesize_outgoing);
1780 /* Attribute Handling. */
1782 const char * const ATTR_INTR = "interrupt";
1783 const char * const ATTR_WAKEUP = "wakeup";
1784 const char * const ATTR_NAKED = "naked";
1785 const char * const ATTR_REENT = "reentrant";
1786 const char * const ATTR_CRIT = "critical";
1787 const char * const ATTR_LOWER = "lower";
1788 const char * const ATTR_UPPER = "upper";
1789 const char * const ATTR_EITHER = "either";
1790 const char * const ATTR_NOINIT = "noinit";
1791 const char * const ATTR_PERSIST = "persistent";
1793 static inline bool
1794 has_attr (const char * attr, tree decl)
1796 if (decl == NULL_TREE)
1797 return false;
1798 return lookup_attribute (attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
1801 static bool
1802 is_interrupt_func (tree decl = current_function_decl)
1804 return has_attr (ATTR_INTR, decl);
1807 /* Returns true if the current function has the "interrupt" attribute. */
1809 bool
1810 msp430_is_interrupt_func (void)
1812 return is_interrupt_func (current_function_decl);
1815 static bool
1816 is_wakeup_func (tree decl = current_function_decl)
1818 return is_interrupt_func (decl) && has_attr (ATTR_WAKEUP, decl);
1821 static inline bool
1822 is_naked_func (tree decl = current_function_decl)
1824 return has_attr (ATTR_NAKED, decl);
1827 static inline bool
1828 is_reentrant_func (tree decl = current_function_decl)
1830 return has_attr (ATTR_REENT, decl);
1833 static inline bool
1834 is_critical_func (tree decl = current_function_decl)
1836 return has_attr (ATTR_CRIT, decl);
1839 static bool
1840 has_section_name (const char * name, tree decl = current_function_decl)
1842 if (decl == NULL_TREE)
1843 return false;
1844 return (DECL_SECTION_NAME (decl)
1845 && (strcmp (name, DECL_SECTION_NAME (decl)) == 0));
1848 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
1849 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS msp430_allocate_stack_slots_for_args
1851 static bool
1852 msp430_allocate_stack_slots_for_args (void)
1854 /* Naked functions should not allocate stack slots for arguments. */
1855 return ! is_naked_func ();
1858 #undef TARGET_WARN_FUNC_RETURN
1859 #define TARGET_WARN_FUNC_RETURN msp430_warn_func_return
1861 static bool
1862 msp430_warn_func_return (tree decl)
1864 /* Naked functions are implemented entirely in assembly, including the
1865 return sequence, so suppress warnings about this. */
1866 return !is_naked_func (decl);
1869 /* Verify MSP430 specific attributes. */
1870 #define TREE_NAME_EQ(NAME, STR) (strcmp (IDENTIFIER_POINTER (NAME), (STR)) == 0)
1872 static tree
1873 msp430_attr (tree * node,
1874 tree name,
1875 tree args,
1876 int flags ATTRIBUTE_UNUSED,
1877 bool * no_add_attrs)
1879 gcc_assert (DECL_P (* node));
1881 if (args != NULL)
1883 /* Only the interrupt attribute takes an argument. */
1884 gcc_assert (TREE_NAME_EQ (name, ATTR_INTR));
1886 tree value = TREE_VALUE (args);
1888 switch (TREE_CODE (value))
1890 case STRING_CST:
1891 if ( strcmp (TREE_STRING_POINTER (value), "reset")
1892 && strcmp (TREE_STRING_POINTER (value), "nmi")
1893 && strcmp (TREE_STRING_POINTER (value), "watchdog"))
1894 /* Allow the attribute to be added - the linker script
1895 being used may still recognise this name. */
1896 warning (OPT_Wattributes,
1897 "unrecognized interrupt vector argument of %qE attribute",
1898 name);
1899 break;
1901 case INTEGER_CST:
1902 if (wi::gtu_p (wi::to_wide (value), 63))
1903 /* Allow the attribute to be added - the linker script
1904 being used may still recognise this value. */
1905 warning (OPT_Wattributes,
1906 "numeric argument of %qE attribute must be in range 0..63",
1907 name);
1908 break;
1910 default:
1911 warning (OPT_Wattributes,
1912 "argument of %qE attribute is not a string constant or number",
1913 name);
1914 *no_add_attrs = true;
1915 break;
1919 const char * message = NULL;
1921 if (TREE_CODE (* node) != FUNCTION_DECL)
1923 message = "%qE attribute only applies to functions";
1925 else if (TREE_NAME_EQ (name, ATTR_INTR))
1927 if (TREE_CODE (TREE_TYPE (* node)) == FUNCTION_TYPE
1928 && ! VOID_TYPE_P (TREE_TYPE (TREE_TYPE (* node))))
1929 message = "interrupt handlers must be void";
1931 if (! TREE_PUBLIC (* node))
1932 message = "interrupt handlers cannot be static";
1934 /* Ensure interrupt handlers never get optimised out. */
1935 TREE_USED (* node) = 1;
1936 DECL_PRESERVE_P (* node) = 1;
1938 else if (TREE_NAME_EQ (name, ATTR_REENT))
1940 if (is_naked_func (* node))
1941 message = "naked functions cannot be reentrant";
1942 else if (is_critical_func (* node))
1943 message = "critical functions cannot be reentrant";
1945 else if (TREE_NAME_EQ (name, ATTR_CRIT))
1947 if (is_naked_func (* node))
1948 message = "naked functions cannot be critical";
1949 else if (is_reentrant_func (* node))
1950 message = "reentrant functions cannot be critical";
1952 else if (TREE_NAME_EQ (name, ATTR_NAKED))
1954 if (is_critical_func (* node))
1955 message = "critical functions cannot be naked";
1956 else if (is_reentrant_func (* node))
1957 message = "reentrant functions cannot be naked";
1960 if (message)
1962 warning (OPT_Wattributes, message, name);
1963 * no_add_attrs = true;
1966 return NULL_TREE;
1969 static tree
1970 msp430_section_attr (tree * node,
1971 tree name,
1972 tree args,
1973 int flags ATTRIBUTE_UNUSED,
1974 bool * no_add_attrs ATTRIBUTE_UNUSED)
1976 gcc_assert (DECL_P (* node));
1977 gcc_assert (args == NULL);
1979 const char * message = NULL;
1981 if (TREE_NAME_EQ (name, ATTR_UPPER))
1983 if (has_attr (ATTR_LOWER, * node))
1984 message = "already marked with 'lower' attribute";
1985 else if (has_attr (ATTR_EITHER, * node))
1986 message = "already marked with 'either' attribute";
1987 else if (! msp430x)
1988 message = "upper attribute needs a 430X cpu";
1990 else if (TREE_NAME_EQ (name, ATTR_LOWER))
1992 if (has_attr (ATTR_UPPER, * node))
1993 message = "already marked with 'upper' attribute";
1994 else if (has_attr (ATTR_EITHER, * node))
1995 message = "already marked with 'either' attribute";
1997 else
1999 gcc_assert (TREE_NAME_EQ (name, ATTR_EITHER));
2001 if (has_attr (ATTR_LOWER, * node))
2002 message = "already marked with 'lower' attribute";
2003 else if (has_attr (ATTR_UPPER, * node))
2004 message = "already marked with 'upper' attribute";
2007 if (message)
2009 warning (OPT_Wattributes, message, name);
2010 * no_add_attrs = true;
2013 return NULL_TREE;
2016 static tree
2017 msp430_data_attr (tree * node,
2018 tree name,
2019 tree args,
2020 int flags ATTRIBUTE_UNUSED,
2021 bool * no_add_attrs ATTRIBUTE_UNUSED)
2023 const char * message = NULL;
2025 gcc_assert (DECL_P (* node));
2026 gcc_assert (args == NULL);
2028 if (TREE_CODE (* node) != VAR_DECL)
2029 message = G_("%qE attribute only applies to variables");
2031 /* Check that it's possible for the variable to have a section. */
2032 if ((TREE_STATIC (* node) || DECL_EXTERNAL (* node) || in_lto_p)
2033 && DECL_SECTION_NAME (* node))
2034 message = G_("%qE attribute cannot be applied to variables with specific sections");
2036 if (!message && TREE_NAME_EQ (name, ATTR_PERSIST) && !TREE_STATIC (* node)
2037 && !TREE_PUBLIC (* node) && !DECL_EXTERNAL (* node))
2038 message = G_("%qE attribute has no effect on automatic variables");
2040 /* It's not clear if there is anything that can be set here to prevent the
2041 front end placing the variable before the back end can handle it, in a
2042 similar way to how DECL_COMMON is used below.
2043 So just place the variable in the .persistent section now. */
2044 if ((TREE_STATIC (* node) || DECL_EXTERNAL (* node) || in_lto_p)
2045 && TREE_NAME_EQ (name, ATTR_PERSIST))
2046 set_decl_section_name (* node, ".persistent");
2048 /* If this var is thought to be common, then change this. Common variables
2049 are assigned to sections before the backend has a chance to process them. */
2050 if (DECL_COMMON (* node))
2051 DECL_COMMON (* node) = 0;
2053 if (message)
2055 warning (OPT_Wattributes, message, name);
2056 * no_add_attrs = true;
2059 return NULL_TREE;
2063 #undef TARGET_ATTRIBUTE_TABLE
2064 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
2066 /* Table of MSP430-specific attributes. */
2067 const struct attribute_spec msp430_attribute_table[] =
2069 /* Name min_num_args type_req, handler
2070 max_num_args, fn_type_req exclude
2071 decl_req affects_type_identity. */
2072 { ATTR_INTR, 0, 1, true, false, false, false, msp430_attr, NULL },
2073 { ATTR_NAKED, 0, 0, true, false, false, false, msp430_attr, NULL },
2074 { ATTR_REENT, 0, 0, true, false, false, false, msp430_attr, NULL },
2075 { ATTR_CRIT, 0, 0, true, false, false, false, msp430_attr, NULL },
2076 { ATTR_WAKEUP, 0, 0, true, false, false, false, msp430_attr, NULL },
2078 { ATTR_LOWER, 0, 0, true, false, false, false, msp430_section_attr,
2079 NULL },
2080 { ATTR_UPPER, 0, 0, true, false, false, false, msp430_section_attr,
2081 NULL },
2082 { ATTR_EITHER, 0, 0, true, false, false, false, msp430_section_attr,
2083 NULL },
2085 { ATTR_NOINIT, 0, 0, true, false, false, false, msp430_data_attr,
2086 NULL },
2087 { ATTR_PERSIST, 0, 0, true, false, false, false, msp430_data_attr,
2088 NULL },
2090 { NULL, 0, 0, false, false, false, false, NULL, NULL }
2093 #undef TARGET_ASM_FUNCTION_PROLOGUE
2094 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
2096 static void
2097 msp430_start_function (FILE *outfile)
2099 int r, n;
2101 fprintf (outfile, "; start of function\n");
2103 if (DECL_ATTRIBUTES (current_function_decl) != NULL_TREE)
2105 fprintf (outfile, "; attributes: ");
2106 if (is_naked_func ())
2107 fprintf (outfile, "naked ");
2108 if (msp430_is_interrupt_func ())
2109 fprintf (outfile, "interrupt ");
2110 if (is_reentrant_func ())
2111 fprintf (outfile, "reentrant ");
2112 if (is_critical_func ())
2113 fprintf (outfile, "critical ");
2114 if (is_wakeup_func ())
2115 fprintf (outfile, "wakeup ");
2116 fprintf (outfile, "\n");
2119 fprintf (outfile, "; framesize_regs: %d\n", cfun->machine->framesize_regs);
2120 fprintf (outfile, "; framesize_locals: %d\n", cfun->machine->framesize_locals);
2121 fprintf (outfile, "; framesize_outgoing: %d\n", cfun->machine->framesize_outgoing);
2122 fprintf (outfile, "; framesize: %d\n", cfun->machine->framesize);
2123 fprintf (outfile, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM));
2124 fprintf (outfile, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM));
2126 n = 0;
2127 fprintf (outfile, "; saved regs:");
2128 for (r = 0; r < ARG_POINTER_REGNUM; r++)
2129 if (cfun->machine->need_to_save [r])
2131 fprintf (outfile, " %s", reg_names [r]);
2132 n = 1;
2134 if (n == 0)
2135 fprintf (outfile, "(none)");
2136 fprintf (outfile, "\n");
2139 /* Common code to change the stack pointer. */
2140 static void
2141 increment_stack (HOST_WIDE_INT amount)
2143 rtx inc;
2144 rtx sp = stack_pointer_rtx;
2146 if (amount == 0)
2147 return;
2149 if (amount < 0)
2151 inc = GEN_INT (- amount);
2152 if (TARGET_LARGE)
2153 F (emit_insn (gen_subpsi3 (sp, sp, inc)));
2154 else
2155 F (emit_insn (gen_subhi3 (sp, sp, inc)));
2157 else
2159 inc = GEN_INT (amount);
2160 if (TARGET_LARGE)
2161 emit_insn (gen_addpsi3 (sp, sp, inc));
2162 else
2163 emit_insn (gen_addhi3 (sp, sp, inc));
2167 void
2168 msp430_start_function (FILE *file, const char *name, tree decl)
2170 tree int_attr;
2172 int_attr = lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl));
2173 if (int_attr != NULL_TREE)
2175 tree intr_vector = TREE_VALUE (int_attr);
2177 if (intr_vector != NULL_TREE)
2179 char buf[101];
2181 /* Interrupt vector sections should be unique, but use of weak
2182 functions implies multiple definitions. */
2183 if (DECL_WEAK (decl))
2185 error ("argument to interrupt attribute is unsupported for weak functions");
2188 intr_vector = TREE_VALUE (intr_vector);
2190 /* The interrupt attribute has a vector value. Turn this into a
2191 section name, switch to that section and put the address of
2192 the current function into that vector slot. Note msp430_attr()
2193 has already verified the vector name for us. */
2194 if (TREE_CODE (intr_vector) == STRING_CST)
2195 sprintf (buf, "__interrupt_vector_%.80s",
2196 TREE_STRING_POINTER (intr_vector));
2197 else /* TREE_CODE (intr_vector) == INTEGER_CST */
2198 sprintf (buf, "__interrupt_vector_%u",
2199 (unsigned int) TREE_INT_CST_LOW (intr_vector));
2201 switch_to_section (get_section (buf, SECTION_CODE, decl));
2202 fputs ("\t.word\t", file);
2203 assemble_name (file, name);
2204 fputc ('\n', file);
2205 fputc ('\t', file);
2209 switch_to_section (function_section (decl));
2210 ASM_OUTPUT_TYPE_DIRECTIVE(file, name, "function");
2211 ASM_OUTPUT_FUNCTION_LABEL (file, name, decl);
2214 static const char * const lower_prefix = ".lower";
2215 static const char * const upper_prefix = ".upper";
2216 static const char * const either_prefix = ".either";
2218 /* Generate a prefix for a section name, based upon
2219 the region into which the object should be placed. */
2221 static const char *
2222 gen_prefix (tree decl)
2224 if (DECL_ONE_ONLY (decl))
2225 return NULL;
2227 /* If the user has specified a particular section then do not use any prefix. */
2228 if (has_attr ("section", decl))
2229 return NULL;
2231 /* If the function has been put in the .lowtext section (because it is an
2232 interrupt handler, and the large memory model is used), then do not add
2233 any prefixes. */
2234 if (has_section_name (".lowtext", decl))
2235 return NULL;
2237 /* If the object has __attribute__((lower)) then use the ".lower." prefix. */
2238 if (has_attr (ATTR_LOWER, decl))
2239 return lower_prefix;
2241 /* If we are compiling for the MSP430 then we do not support the upper region. */
2242 if (! msp430x)
2243 return NULL;
2245 if (has_attr (ATTR_UPPER, decl))
2246 return upper_prefix;
2248 if (has_attr (ATTR_EITHER, decl))
2249 return either_prefix;
2251 if (TREE_CODE (decl) == FUNCTION_DECL)
2253 if (msp430_code_region == MSP430_REGION_LOWER)
2254 return lower_prefix;
2256 if (msp430_code_region == MSP430_REGION_UPPER)
2257 return upper_prefix;
2259 if (msp430_code_region == MSP430_REGION_EITHER)
2260 return either_prefix;
2262 else
2264 if (msp430_data_region == MSP430_REGION_LOWER)
2265 return lower_prefix;
2267 if (msp430_data_region == MSP430_REGION_UPPER)
2268 return upper_prefix;
2270 if (msp430_data_region == MSP430_REGION_EITHER)
2271 return either_prefix;
2274 return NULL;
2277 static section * noinit_section;
2278 static section * persist_section;
2280 #undef TARGET_ASM_INIT_SECTIONS
2281 #define TARGET_ASM_INIT_SECTIONS msp430_init_sections
2283 static void
2284 msp430_init_sections (void)
2286 noinit_section = get_unnamed_section (0, output_section_asm_op, ".section .noinit,\"aw\"");
2287 persist_section = get_unnamed_section (0, output_section_asm_op, ".section .persistent,\"aw\"");
2290 #undef TARGET_ASM_SELECT_SECTION
2291 #define TARGET_ASM_SELECT_SECTION msp430_select_section
2293 static section *
2294 msp430_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
2296 gcc_assert (decl != NULL_TREE);
2298 if (TREE_CODE (decl) == STRING_CST
2299 || TREE_CODE (decl) == CONSTRUCTOR
2300 || TREE_CODE (decl) == INTEGER_CST
2301 || TREE_CODE (decl) == VECTOR_CST
2302 || TREE_CODE (decl) == COMPLEX_CST)
2303 return default_select_section (decl, reloc, align);
2305 /* In large mode we must make sure that interrupt handlers are put into
2306 low memory as the vector table only accepts 16-bit addresses. */
2307 if (TARGET_LARGE && TREE_CODE (decl) == FUNCTION_DECL && is_interrupt_func (decl))
2308 return get_section (".lowtext", SECTION_CODE | SECTION_WRITE , decl);
2310 const char * prefix = gen_prefix (decl);
2311 if (prefix == NULL)
2313 if (TREE_CODE (decl) == FUNCTION_DECL)
2314 return text_section;
2315 else if (has_attr (ATTR_NOINIT, decl))
2316 return noinit_section;
2317 else if (has_attr (ATTR_PERSIST, decl))
2318 return persist_section;
2319 else
2320 return default_select_section (decl, reloc, align);
2323 const char * sec;
2324 switch (categorize_decl_for_section (decl, reloc))
2326 case SECCAT_TEXT: sec = ".text"; break;
2327 case SECCAT_DATA: sec = ".data"; break;
2328 case SECCAT_BSS: sec = ".bss"; break;
2329 case SECCAT_RODATA: sec = ".rodata"; break;
2331 case SECCAT_RODATA_MERGE_STR:
2332 case SECCAT_RODATA_MERGE_STR_INIT:
2333 case SECCAT_RODATA_MERGE_CONST:
2334 case SECCAT_SRODATA:
2335 case SECCAT_DATA_REL:
2336 case SECCAT_DATA_REL_LOCAL:
2337 case SECCAT_DATA_REL_RO:
2338 case SECCAT_DATA_REL_RO_LOCAL:
2339 case SECCAT_SDATA:
2340 case SECCAT_SBSS:
2341 case SECCAT_TDATA:
2342 case SECCAT_TBSS:
2343 return default_select_section (decl, reloc, align);
2345 default:
2346 gcc_unreachable ();
2349 const char * dec_name = DECL_SECTION_NAME (decl);
2350 char * name = ACONCAT ((prefix, sec, dec_name, NULL));
2352 return get_named_section (decl, name, 0);
2355 #undef TARGET_ASM_FUNCTION_SECTION
2356 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
2358 static section *
2359 msp430_function_section (tree decl, enum node_frequency freq, bool startup, bool exit)
2361 const char * name;
2363 gcc_assert (DECL_SECTION_NAME (decl) != NULL);
2364 name = DECL_SECTION_NAME (decl);
2366 const char * prefix = gen_prefix (decl);
2367 if (prefix == NULL
2368 || strncmp (name, prefix, strlen (prefix)) == 0)
2369 return default_function_section (decl, freq, startup, exit);
2371 name = ACONCAT ((prefix, name, NULL));
2372 return get_named_section (decl, name, 0);
2375 #undef TARGET_SECTION_TYPE_FLAGS
2376 #define TARGET_SECTION_TYPE_FLAGS msp430_section_type_flags
2378 unsigned int
2379 msp430_section_type_flags (tree decl, const char * name, int reloc)
2381 if (strncmp (name, lower_prefix, strlen (lower_prefix)) == 0)
2382 name += strlen (lower_prefix);
2383 else if (strncmp (name, upper_prefix, strlen (upper_prefix)) == 0)
2384 name += strlen (upper_prefix);
2385 else if (strncmp (name, either_prefix, strlen (either_prefix)) == 0)
2386 name += strlen (either_prefix);
2387 else if (strcmp (name, ".noinit") == 0)
2388 return SECTION_WRITE | SECTION_BSS | SECTION_NOTYPE;
2389 else if (strcmp (name, ".persistent") == 0)
2390 return SECTION_WRITE | SECTION_NOTYPE;
2392 return default_section_type_flags (decl, name, reloc);
2395 #undef TARGET_ASM_UNIQUE_SECTION
2396 #define TARGET_ASM_UNIQUE_SECTION msp430_unique_section
2398 static void
2399 msp430_unique_section (tree decl, int reloc)
2401 gcc_assert (decl != NULL_TREE);
2403 /* In large mode we must make sure that interrupt handlers are put into
2404 low memory as the vector table only accepts 16-bit addresses. */
2405 if (TARGET_LARGE && TREE_CODE (decl) == FUNCTION_DECL && is_interrupt_func (decl))
2407 set_decl_section_name (decl, ".lowtext");
2408 return;
2411 default_unique_section (decl, reloc);
2413 const char * prefix;
2415 if ( TREE_CODE (decl) == STRING_CST
2416 || TREE_CODE (decl) == CONSTRUCTOR
2417 || TREE_CODE (decl) == INTEGER_CST
2418 || TREE_CODE (decl) == VECTOR_CST
2419 || TREE_CODE (decl) == COMPLEX_CST
2420 || (prefix = gen_prefix (decl)) == NULL
2422 return;
2424 const char * dec_name = DECL_SECTION_NAME (decl);
2425 char * name = ACONCAT ((prefix, dec_name, NULL));
2427 set_decl_section_name (decl, name);
2430 /* Emit a declaration of a common symbol.
2431 If a data region is in use then put the symbol into the
2432 equivalent .bss section instead. */
2434 void
2435 msp430_output_aligned_decl_common (FILE * stream,
2436 const tree decl,
2437 const char * name,
2438 unsigned HOST_WIDE_INT size,
2439 unsigned int align)
2441 if (msp430_data_region == MSP430_REGION_ANY)
2443 fprintf (stream, COMMON_ASM_OP);
2444 assemble_name (stream, name);
2445 fprintf (stream, "," HOST_WIDE_INT_PRINT_UNSIGNED",%u\n",
2446 size, align / BITS_PER_UNIT);
2448 else
2450 section * sec;
2452 if (decl)
2453 sec = msp430_select_section (decl, 0, align);
2454 else
2455 switch (msp430_data_region)
2457 case MSP430_REGION_UPPER: sec = get_named_section (NULL, ".upper.bss", 0); break;
2458 case MSP430_REGION_LOWER: sec = get_named_section (NULL, ".lower.bss", 0); break;
2459 case MSP430_REGION_EITHER: sec = get_named_section (NULL, ".either.bss", 0); break;
2460 default:
2461 gcc_unreachable ();
2463 gcc_assert (sec != NULL);
2465 switch_to_section (sec);
2466 ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
2467 targetm.asm_out.globalize_label (stream, name);
2468 ASM_WEAKEN_LABEL (stream, name);
2469 ASM_OUTPUT_LABEL (stream, name);
2470 ASM_OUTPUT_SKIP (stream, size ? size : 1);
2474 bool
2475 msp430_do_not_relax_short_jumps (void)
2477 /* When placing code into "either" low or high memory we do not want the linker
2478 to grow the size of sections, which it can do if it is encounters a branch to
2479 a label that is too far away. So we tell the cbranch patterns to avoid using
2480 short jumps when there is a chance that the instructions will end up in a low
2481 section. */
2482 return
2483 msp430_code_region == MSP430_REGION_EITHER
2484 || msp430_code_region == MSP430_REGION_LOWER
2485 || has_attr (ATTR_EITHER, current_function_decl)
2486 || has_attr (ATTR_LOWER, current_function_decl);
2489 enum msp430_builtin
2491 MSP430_BUILTIN_BIC_SR,
2492 MSP430_BUILTIN_BIS_SR,
2493 MSP430_BUILTIN_DELAY_CYCLES,
2494 MSP430_BUILTIN_max
2497 static GTY(()) tree msp430_builtins [(int) MSP430_BUILTIN_max];
2499 static void
2500 msp430_init_builtins (void)
2502 tree void_ftype_int = build_function_type_list (void_type_node, integer_type_node, NULL);
2503 tree void_ftype_longlong = build_function_type_list (void_type_node, long_long_integer_type_node, NULL);
2505 msp430_builtins[MSP430_BUILTIN_BIC_SR] =
2506 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int,
2507 MSP430_BUILTIN_BIC_SR, BUILT_IN_MD, NULL, NULL_TREE);
2509 msp430_builtins[MSP430_BUILTIN_BIS_SR] =
2510 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int,
2511 MSP430_BUILTIN_BIS_SR, BUILT_IN_MD, NULL, NULL_TREE);
2513 msp430_builtins[MSP430_BUILTIN_DELAY_CYCLES] =
2514 add_builtin_function ( "__delay_cycles", void_ftype_longlong,
2515 MSP430_BUILTIN_DELAY_CYCLES, BUILT_IN_MD, NULL, NULL_TREE);
2518 static tree
2519 msp430_builtin_decl (unsigned code, bool initialize ATTRIBUTE_UNUSED)
2521 switch (code)
2523 case MSP430_BUILTIN_BIC_SR:
2524 case MSP430_BUILTIN_BIS_SR:
2525 case MSP430_BUILTIN_DELAY_CYCLES:
2526 return msp430_builtins[code];
2527 default:
2528 return error_mark_node;
2532 /* These constants are really register reads, which are faster than
2533 regular constants. */
2534 static int
2535 cg_magic_constant (HOST_WIDE_INT c)
2537 switch (c)
2539 case 0xffff:
2540 case -1:
2541 case 0:
2542 case 1:
2543 case 2:
2544 case 4:
2545 case 8:
2546 return 1;
2547 default:
2548 return 0;
2552 static rtx
2553 msp430_expand_delay_cycles (rtx arg)
2555 HOST_WIDE_INT i, c, n;
2556 /* extra cycles for MSP430X instructions */
2557 #define CYCX(M,X) (msp430x ? (X) : (M))
2559 if (GET_CODE (arg) != CONST_INT)
2561 error ("__delay_cycles() only takes constant arguments");
2562 return NULL_RTX;
2565 c = INTVAL (arg);
2567 if (HOST_BITS_PER_WIDE_INT > 32)
2569 if (c < 0)
2571 error ("__delay_cycles only takes non-negative cycle counts");
2572 return NULL_RTX;
2576 emit_insn (gen_delay_cycles_start (arg));
2578 /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
2579 if (c > 3 * 0xffff + CYCX (7, 10))
2581 n = c;
2582 /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
2583 if (c >= 0x10000 * 7 + CYCX (14, 16))
2585 i = 0x10000;
2586 c -= CYCX (14, 16) + 7 * 0x10000;
2587 i += c / 4;
2588 c %= 4;
2589 if ((unsigned long long) i > 0xffffffffULL)
2591 error ("__delay_cycles is limited to 32-bit loop counts");
2592 return NULL_RTX;
2595 else
2597 i = (c - CYCX (14, 16)) / 7;
2598 c -= CYCX (14, 16) + i * 7;
2601 if (cg_magic_constant (i & 0xffff))
2602 c ++;
2603 if (cg_magic_constant ((i >> 16) & 0xffff))
2604 c ++;
2606 if (msp430x)
2607 emit_insn (gen_delay_cycles_32x (GEN_INT (i), GEN_INT (n - c)));
2608 else
2609 emit_insn (gen_delay_cycles_32 (GEN_INT (i), GEN_INT (n - c)));
2612 /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
2613 if (c > 12)
2615 n = c;
2616 i = (c - CYCX (7, 10)) / 3;
2617 c -= CYCX (7, 10) + i * 3;
2619 if (cg_magic_constant (i))
2620 c ++;
2622 if (msp430x)
2623 emit_insn (gen_delay_cycles_16x (GEN_INT (i), GEN_INT (n - c)));
2624 else
2625 emit_insn (gen_delay_cycles_16 (GEN_INT (i), GEN_INT (n - c)));
2628 while (c > 1)
2630 emit_insn (gen_delay_cycles_2 ());
2631 c -= 2;
2634 if (c)
2636 emit_insn (gen_delay_cycles_1 ());
2637 c -= 1;
2640 emit_insn (gen_delay_cycles_end (arg));
2642 return NULL_RTX;
2645 static rtx
2646 msp430_expand_builtin (tree exp,
2647 rtx target ATTRIBUTE_UNUSED,
2648 rtx subtarget ATTRIBUTE_UNUSED,
2649 machine_mode mode ATTRIBUTE_UNUSED,
2650 int ignore ATTRIBUTE_UNUSED)
2652 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
2653 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2654 rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
2656 if (fcode == MSP430_BUILTIN_DELAY_CYCLES)
2657 return msp430_expand_delay_cycles (arg1);
2659 if (! msp430_is_interrupt_func ())
2661 error ("MSP430 builtin functions only work inside interrupt handlers");
2662 return NULL_RTX;
2665 if (! REG_P (arg1) && ! CONSTANT_P (arg1))
2666 arg1 = force_reg (mode, arg1);
2668 switch (fcode)
2670 case MSP430_BUILTIN_BIC_SR: emit_insn (gen_bic_SR (arg1)); break;
2671 case MSP430_BUILTIN_BIS_SR: emit_insn (gen_bis_SR (arg1)); break;
2672 default:
2673 internal_error ("bad builtin code");
2674 break;
2676 return NULL_RTX;
2679 #undef TARGET_INIT_BUILTINS
2680 #define TARGET_INIT_BUILTINS msp430_init_builtins
2682 #undef TARGET_EXPAND_BUILTIN
2683 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
2685 #undef TARGET_BUILTIN_DECL
2686 #define TARGET_BUILTIN_DECL msp430_builtin_decl
2688 void
2689 msp430_expand_prologue (void)
2691 int i, j;
2692 int fs;
2693 /* Always use stack_pointer_rtx instead of calling
2694 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
2695 that there is a single rtx representing the stack pointer,
2696 namely stack_pointer_rtx, and uses == to recognize it. */
2697 rtx sp = stack_pointer_rtx;
2698 rtx p;
2700 if (is_naked_func ())
2702 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2703 examines the output of the gen_prologue() function. */
2704 emit_insn (gen_rtx_CLOBBER (VOIDmode, GEN_INT (0)));
2705 return;
2708 emit_insn (gen_prologue_start_marker ());
2710 if (is_critical_func ())
2712 emit_insn (gen_push_intr_state ());
2713 emit_insn (gen_disable_interrupts ());
2715 else if (is_reentrant_func ())
2716 emit_insn (gen_disable_interrupts ());
2718 if (!cfun->machine->computed)
2719 msp430_compute_frame_info ();
2721 if (flag_stack_usage_info)
2722 current_function_static_stack_size = cfun->machine->framesize;
2724 if (crtl->args.pretend_args_size)
2726 rtx note;
2728 gcc_assert (crtl->args.pretend_args_size == 2);
2730 p = emit_insn (gen_grow_and_swap ());
2732 /* Document the stack decrement... */
2733 note = F (gen_rtx_SET (stack_pointer_rtx,
2734 gen_rtx_MINUS (Pmode, stack_pointer_rtx, GEN_INT (2))));
2735 add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
2737 /* ...and the establishment of a new location for the return address. */
2738 note = F (gen_rtx_SET (gen_rtx_MEM (Pmode,
2739 gen_rtx_PLUS (Pmode,
2740 stack_pointer_rtx,
2741 GEN_INT (-2))),
2742 pc_rtx));
2743 add_reg_note (p, REG_CFA_OFFSET, note);
2744 F (p);
2747 for (i = 15; i >= 4; i--)
2748 if (cfun->machine->need_to_save [i])
2750 int seq, count;
2751 rtx note;
2753 for (seq = i - 1; seq >= 4 && cfun->machine->need_to_save[seq]; seq --)
2755 count = i - seq;
2757 if (msp430x)
2759 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
2760 p = F (emit_insn (gen_pushm (gen_rtx_REG (Pmode, i),
2761 GEN_INT (count))));
2763 note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1));
2765 XVECEXP (note, 0, 0)
2766 = F (gen_rtx_SET (stack_pointer_rtx,
2767 gen_rtx_PLUS (Pmode,
2768 stack_pointer_rtx,
2769 GEN_INT (count * (TARGET_LARGE ? -4 : -2)))));
2771 /* *sp-- = R[i-j] */
2772 /* sp+N R10
2774 sp R4 */
2775 for (j = 0; j < count; j ++)
2777 rtx addr;
2778 int ofs = (count - j - 1) * (TARGET_LARGE ? 4 : 2);
2780 if (ofs)
2781 addr = gen_rtx_PLUS (Pmode, sp, GEN_INT (ofs));
2782 else
2783 addr = stack_pointer_rtx;
2785 XVECEXP (note, 0, j + 1) =
2786 F (gen_rtx_SET (gen_rtx_MEM (Pmode, addr),
2787 gen_rtx_REG (Pmode, i - j)) );
2790 add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
2791 i -= count - 1;
2793 else
2794 F (emit_insn (gen_push (gen_rtx_REG (Pmode, i))));
2797 if (frame_pointer_needed)
2798 F (emit_move_insn (gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM), sp));
2800 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
2802 increment_stack (- fs);
2804 emit_insn (gen_prologue_end_marker ());
2807 void
2808 msp430_expand_epilogue (int is_eh)
2810 int i;
2811 int fs;
2812 int helper_n = 0;
2814 if (is_naked_func ())
2816 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2817 examines the output of the gen_epilogue() function. */
2818 emit_insn (gen_rtx_CLOBBER (VOIDmode, GEN_INT (0)));
2819 return;
2822 if (cfun->machine->need_to_save [10])
2824 /* Check for a helper function. */
2825 helper_n = 7; /* For when the loop below never sees a match. */
2826 for (i = 9; i >= 4; i--)
2827 if (!cfun->machine->need_to_save [i])
2829 helper_n = 10 - i;
2830 for (; i >= 4; i--)
2831 if (cfun->machine->need_to_save [i])
2833 helper_n = 0;
2834 break;
2836 break;
2840 emit_insn (gen_epilogue_start_marker ());
2842 if (cfun->decl && strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun->decl)), "main") == 0)
2843 emit_insn (gen_msp430_refsym_need_exit ());
2845 if (is_wakeup_func ())
2846 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
2847 status register current residing on the stack. When this function
2848 executes its RETI instruction the SR will be updated with this saved
2849 value, thus ensuring that the processor is woken up from any low power
2850 state in which it may be residing. */
2851 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
2853 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
2855 increment_stack (fs);
2857 if (is_eh)
2859 /* We need to add the right "SP" register save just after the
2860 regular ones, so that when we pop it off we're in the EH
2861 return frame, not this one. This overwrites our own return
2862 address, but we're not going to be returning anyway. */
2863 rtx r12 = gen_rtx_REG (Pmode, 12);
2864 rtx (*addPmode)(rtx, rtx, rtx) = TARGET_LARGE ? gen_addpsi3 : gen_addhi3;
2866 /* R12 will hold the new SP. */
2867 i = cfun->machine->framesize_regs;
2868 emit_move_insn (r12, stack_pointer_rtx);
2869 emit_insn (addPmode (r12, r12, EH_RETURN_STACKADJ_RTX));
2870 emit_insn (addPmode (r12, r12, GEN_INT (i)));
2871 emit_move_insn (gen_rtx_MEM (Pmode, plus_constant (Pmode, stack_pointer_rtx, i)), r12);
2874 for (i = 4; i <= 15; i++)
2875 if (cfun->machine->need_to_save [i])
2877 int seq, count;
2879 for (seq = i + 1; seq <= 15 && cfun->machine->need_to_save[seq]; seq ++)
2881 count = seq - i;
2883 if (msp430x)
2885 /* Note: With TARGET_LARGE we still use
2886 POPM as POPX.A is two bytes bigger. */
2887 emit_insn (gen_popm (stack_pointer_rtx, GEN_INT (seq - 1),
2888 GEN_INT (count)));
2889 i += count - 1;
2891 else if (i == 11 - helper_n
2892 && ! msp430_is_interrupt_func ()
2893 && ! is_reentrant_func ()
2894 && ! is_critical_func ()
2895 && crtl->args.pretend_args_size == 0
2896 /* Calling the helper takes as many bytes as the POP;RET sequence. */
2897 && helper_n > 1
2898 && !is_eh)
2900 emit_insn (gen_epilogue_helper (GEN_INT (helper_n)));
2901 return;
2903 else
2904 emit_insn (gen_pop (gen_rtx_REG (Pmode, i)));
2907 if (is_eh)
2909 /* Also pop SP, which puts us into the EH return frame. Except
2910 that you can't "pop" sp, you have to just load it off the
2911 stack. */
2912 emit_move_insn (stack_pointer_rtx, gen_rtx_MEM (Pmode, stack_pointer_rtx));
2915 if (crtl->args.pretend_args_size)
2916 emit_insn (gen_swap_and_shrink ());
2918 if (is_critical_func ())
2919 emit_insn (gen_pop_intr_state ());
2920 else if (is_reentrant_func ())
2921 emit_insn (gen_enable_interrupts ());
2923 emit_jump_insn (gen_msp_return ());
2926 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
2927 m32c_emit_eh_epilogue. */
2929 msp430_eh_return_stackadj_rtx (void)
2931 if (!cfun->machine->eh_stack_adjust)
2933 rtx sa;
2935 sa = gen_rtx_REG (Pmode, 15);
2936 cfun->machine->eh_stack_adjust = sa;
2938 return cfun->machine->eh_stack_adjust;
2941 /* This function is called before reload, to "fix" the stack in
2942 preparation for an EH return. */
2943 void
2944 msp430_expand_eh_return (rtx eh_handler)
2946 /* These are all Pmode */
2947 rtx ap, sa, ra, tmp;
2949 ap = arg_pointer_rtx;
2950 sa = msp430_eh_return_stackadj_rtx ();
2951 ra = eh_handler;
2953 tmp = ap;
2954 tmp = gen_rtx_PLUS (Pmode, ap, sa);
2955 tmp = plus_constant (Pmode, tmp, TARGET_LARGE ? -4 : -2);
2956 tmp = gen_rtx_MEM (Pmode, tmp);
2957 emit_move_insn (tmp, ra);
2960 #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
2961 #define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
2962 void
2963 msp430_init_dwarf_reg_sizes_extra (tree address)
2965 int i;
2966 rtx addr = expand_normal (address);
2967 rtx mem = gen_rtx_MEM (BLKmode, addr);
2969 /* This needs to match msp430_unwind_word_mode (above). */
2970 if (!msp430x)
2971 return;
2973 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2975 unsigned int dnum = DWARF_FRAME_REGNUM (i);
2976 unsigned int rnum = DWARF2_FRAME_REG_OUT (dnum, 1);
2978 if (rnum < DWARF_FRAME_REGISTERS)
2980 HOST_WIDE_INT offset = rnum * GET_MODE_SIZE (QImode);
2982 emit_move_insn (adjust_address (mem, QImode, offset),
2983 gen_int_mode (4, QImode));
2988 /* This is a list of MD patterns that implement fixed-count shifts. */
2989 static struct
2991 const char *name;
2992 int count;
2993 int need_430x;
2994 rtx (*genfunc)(rtx,rtx);
2996 const_shift_helpers[] =
2998 #define CSH(N,C,X,G) { "__mspabi_" N, C, X, gen_##G }
3000 CSH ("slli", 1, 1, slli_1),
3001 CSH ("slll", 1, 1, slll_1),
3002 CSH ("slll", 2, 1, slll_2),
3004 CSH ("srai", 1, 0, srai_1),
3005 CSH ("sral", 1, 0, sral_1),
3006 CSH ("sral", 2, 0, sral_2),
3008 CSH ("srll", 1, 0, srll_1),
3009 CSH ("srll", 2, 1, srll_2x),
3010 { 0, 0, 0, 0 }
3011 #undef CSH
3014 /* The MSP430 ABI defines a number of helper functions that should be
3015 used for, for example, 32-bit shifts. This function is called to
3016 emit such a function, using the table above to optimize some
3017 cases. */
3018 void
3019 msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variants)
3021 rtx c, f;
3022 char *helper_const = NULL;
3023 int arg2 = 13;
3024 int arg1sz = 1;
3025 machine_mode arg0mode = GET_MODE (operands[0]);
3026 machine_mode arg1mode = GET_MODE (operands[1]);
3027 machine_mode arg2mode = GET_MODE (operands[2]);
3028 int have_430x = msp430x ? 1 : 0;
3030 if (CONST_INT_P (operands[2]))
3032 int i;
3034 for (i=0; const_shift_helpers[i].name; i++)
3036 if (const_shift_helpers[i].need_430x <= have_430x
3037 && strcmp (helper_name, const_shift_helpers[i].name) == 0
3038 && INTVAL (operands[2]) == const_shift_helpers[i].count)
3040 emit_insn (const_shift_helpers[i].genfunc (operands[0], operands[1]));
3041 return;
3046 if (arg1mode == VOIDmode)
3047 arg1mode = arg0mode;
3048 if (arg2mode == VOIDmode)
3049 arg2mode = arg0mode;
3051 if (arg1mode == SImode)
3053 arg2 = 14;
3054 arg1sz = 2;
3057 if (const_variants
3058 && CONST_INT_P (operands[2])
3059 && INTVAL (operands[2]) >= 1
3060 && INTVAL (operands[2]) <= 15)
3062 /* Note that the INTVAL is limited in value and length by the conditional above. */
3063 int len = strlen (helper_name) + 4;
3064 helper_const = (char *) xmalloc (len);
3065 snprintf (helper_const, len, "%s_%d", helper_name, (int) INTVAL (operands[2]));
3068 emit_move_insn (gen_rtx_REG (arg1mode, 12),
3069 operands[1]);
3070 if (!helper_const)
3071 emit_move_insn (gen_rtx_REG (arg2mode, arg2),
3072 operands[2]);
3074 c = gen_call_value_internal (gen_rtx_REG (arg0mode, 12),
3075 gen_rtx_SYMBOL_REF (VOIDmode, helper_const ? helper_const : helper_name),
3076 GEN_INT (0));
3077 c = emit_call_insn (c);
3078 RTL_CONST_CALL_P (c) = 1;
3080 f = 0;
3081 use_regs (&f, 12, arg1sz);
3082 if (!helper_const)
3083 use_regs (&f, arg2, 1);
3084 add_function_usage_to (c, f);
3086 emit_move_insn (operands[0],
3087 gen_rtx_REG (arg0mode, 12));
3090 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
3091 void
3092 msp430_fixup_compare_operands (machine_mode my_mode, rtx * operands)
3094 /* constants we're looking for, not constants which are allowed. */
3095 int const_op_idx = 1;
3097 if (msp430_reversible_cmp_operator (operands[0], VOIDmode))
3098 const_op_idx = 2;
3100 if (GET_CODE (operands[const_op_idx]) != REG
3101 && GET_CODE (operands[const_op_idx]) != MEM)
3102 operands[const_op_idx] = copy_to_mode_reg (my_mode, operands[const_op_idx]);
3105 /* Simplify_gen_subreg() doesn't handle memory references the way we
3106 need it to below, so we use this function for when we must get a
3107 valid subreg in a "natural" state. */
3109 msp430_subreg (machine_mode mode, rtx r, machine_mode omode, int byte)
3111 rtx rv;
3113 if (GET_CODE (r) == SUBREG
3114 && SUBREG_BYTE (r) == 0)
3116 rtx ireg = SUBREG_REG (r);
3117 machine_mode imode = GET_MODE (ireg);
3119 /* special case for (HI (SI (PSI ...), 0)) */
3120 if (imode == PSImode
3121 && mode == HImode
3122 && byte == 0)
3123 rv = gen_rtx_SUBREG (mode, ireg, byte);
3124 else
3125 rv = simplify_gen_subreg (mode, ireg, imode, byte);
3127 else if (GET_CODE (r) == MEM)
3128 rv = adjust_address (r, mode, byte);
3129 else if (GET_CODE (r) == SYMBOL_REF
3130 && (byte == 0 || byte == 2)
3131 && mode == HImode)
3133 rv = gen_rtx_ZERO_EXTRACT (HImode, r, GEN_INT (16), GEN_INT (8*byte));
3134 rv = gen_rtx_CONST (HImode, r);
3136 else
3137 rv = simplify_gen_subreg (mode, r, omode, byte);
3139 if (!rv)
3140 gcc_unreachable ();
3142 return rv;
3145 /* Called by movsi_x to generate the HImode operands. */
3146 void
3147 msp430_split_movsi (rtx *operands)
3149 rtx op00, op02, op10, op12;
3151 op00 = msp430_subreg (HImode, operands[0], SImode, 0);
3152 op02 = msp430_subreg (HImode, operands[0], SImode, 2);
3154 if (GET_CODE (operands[1]) == CONST
3155 || GET_CODE (operands[1]) == SYMBOL_REF)
3157 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
3158 op10 = gen_rtx_CONST (HImode, op10);
3159 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
3160 op12 = gen_rtx_CONST (HImode, op12);
3162 else
3164 op10 = msp430_subreg (HImode, operands[1], SImode, 0);
3165 op12 = msp430_subreg (HImode, operands[1], SImode, 2);
3168 if (rtx_equal_p (operands[0], operands[1]))
3170 operands[2] = op02;
3171 operands[4] = op12;
3172 operands[3] = op00;
3173 operands[5] = op10;
3175 else if (rtx_equal_p (op00, op12)
3176 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
3177 || (REG_P (op00) && reg_mentioned_p (op00, op10))
3178 /* Or storing (rN) into mem (rN). */
3179 || (REG_P (op10) && reg_mentioned_p (op10, op00))
3182 operands[2] = op02;
3183 operands[4] = op12;
3184 operands[3] = op00;
3185 operands[5] = op10;
3187 else
3189 operands[2] = op00;
3190 operands[4] = op10;
3191 operands[3] = op02;
3192 operands[5] = op12;
3197 /* The MSPABI specifies the names of various helper functions, many of
3198 which are compatible with GCC's helpers. This table maps the GCC
3199 name to the MSPABI name. */
3200 static const struct
3202 char const * const gcc_name;
3203 char const * const ti_name;
3205 helper_function_name_mappings [] =
3207 /* Floating point to/from integer conversions. */
3208 { "__truncdfsf2", "__mspabi_cvtdf" },
3209 { "__extendsfdf2", "__mspabi_cvtfd" },
3210 { "__fixdfhi", "__mspabi_fixdi" },
3211 { "__fixdfsi", "__mspabi_fixdli" },
3212 { "__fixdfdi", "__mspabi_fixdlli" },
3213 { "__fixunsdfhi", "__mspabi_fixdu" },
3214 { "__fixunsdfsi", "__mspabi_fixdul" },
3215 { "__fixunsdfdi", "__mspabi_fixdull" },
3216 { "__fixsfhi", "__mspabi_fixfi" },
3217 { "__fixsfsi", "__mspabi_fixfli" },
3218 { "__fixsfdi", "__mspabi_fixflli" },
3219 { "__fixunsfhi", "__mspabi_fixfu" },
3220 { "__fixunsfsi", "__mspabi_fixful" },
3221 { "__fixunsfdi", "__mspabi_fixfull" },
3222 { "__floathisf", "__mspabi_fltif" },
3223 { "__floatsisf", "__mspabi_fltlif" },
3224 { "__floatdisf", "__mspabi_fltllif" },
3225 { "__floathidf", "__mspabi_fltid" },
3226 { "__floatsidf", "__mspabi_fltlid" },
3227 { "__floatdidf", "__mspabi_fltllid" },
3228 { "__floatunhisf", "__mspabi_fltuf" },
3229 { "__floatunsisf", "__mspabi_fltulf" },
3230 { "__floatundisf", "__mspabi_fltullf" },
3231 { "__floatunhidf", "__mspabi_fltud" },
3232 { "__floatunsidf", "__mspabi_fltuld" },
3233 { "__floatundidf", "__mspabi_fltulld" },
3235 /* Floating point comparisons. */
3236 /* GCC uses individual functions for each comparison, TI uses one
3237 compare <=> function. */
3239 /* Floating point arithmatic */
3240 { "__adddf3", "__mspabi_addd" },
3241 { "__addsf3", "__mspabi_addf" },
3242 { "__divdf3", "__mspabi_divd" },
3243 { "__divsf3", "__mspabi_divf" },
3244 { "__muldf3", "__mspabi_mpyd" },
3245 { "__mulsf3", "__mspabi_mpyf" },
3246 { "__subdf3", "__mspabi_subd" },
3247 { "__subsf3", "__mspabi_subf" },
3248 /* GCC does not use helper functions for negation */
3250 /* Integer multiply, divide, remainder. */
3251 { "__mulhi3", "__mspabi_mpyi" },
3252 { "__mulsi3", "__mspabi_mpyl" },
3253 { "__muldi3", "__mspabi_mpyll" },
3254 #if 0
3255 /* Clarify signed vs unsigned first. */
3256 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
3257 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
3258 #endif
3260 { "__divhi3", "__mspabi_divi" },
3261 { "__divsi3", "__mspabi_divli" },
3262 { "__divdi3", "__mspabi_divlli" },
3263 { "__udivhi3", "__mspabi_divu" },
3264 { "__udivsi3", "__mspabi_divul" },
3265 { "__udivdi3", "__mspabi_divull" },
3266 { "__modhi3", "__mspabi_remi" },
3267 { "__modsi3", "__mspabi_remli" },
3268 { "__moddi3", "__mspabi_remlli" },
3269 { "__umodhi3", "__mspabi_remu" },
3270 { "__umodsi3", "__mspabi_remul" },
3271 { "__umoddi3", "__mspabi_remull" },
3273 /* Bitwise operations. */
3274 /* Rotation - no rotation support yet. */
3275 /* Logical left shift - gcc already does these itself. */
3276 /* Arithmetic left shift - gcc already does these itself. */
3277 /* Arithmetic right shift - gcc already does these itself. */
3279 { NULL, NULL }
3282 /* Returns true if the current MCU supports an F5xxx series
3283 hardware multiper. */
3285 bool
3286 msp430_use_f5_series_hwmult (void)
3288 static const char * cached_match = NULL;
3289 static bool cached_result;
3291 if (msp430_hwmult_type == MSP430_HWMULT_F5SERIES)
3292 return true;
3294 if (target_mcu == NULL || msp430_hwmult_type != MSP430_HWMULT_AUTO)
3295 return false;
3297 if (target_mcu == cached_match)
3298 return cached_result;
3300 cached_match = target_mcu;
3302 if (strncasecmp (target_mcu, "msp430f5", 8) == 0)
3303 return cached_result = true;
3304 if (strncasecmp (target_mcu, "msp430fr5", 9) == 0)
3305 return cached_result = true;
3306 if (strncasecmp (target_mcu, "msp430f6", 8) == 0)
3307 return cached_result = true;
3309 int i;
3311 /* FIXME: This array is alpha sorted - we could use a binary search. */
3312 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
3313 if (strcasecmp (target_mcu, msp430_mcu_data[i].name) == 0)
3314 return cached_result = msp430_mcu_data[i].hwmpy == 8;
3316 return cached_result = false;
3319 /* Returns true if the current MCU has a second generation
3320 32-bit hardware multiplier. */
3322 static bool
3323 use_32bit_hwmult (void)
3325 static const char * cached_match = NULL;
3326 static bool cached_result;
3327 int i;
3329 if (msp430_hwmult_type == MSP430_HWMULT_LARGE)
3330 return true;
3332 if (target_mcu == NULL || msp430_hwmult_type != MSP430_HWMULT_AUTO)
3333 return false;
3335 if (target_mcu == cached_match)
3336 return cached_result;
3338 cached_match = target_mcu;
3340 /* FIXME: This array is alpha sorted - we could use a binary search. */
3341 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
3342 if (strcasecmp (target_mcu, msp430_mcu_data[i].name) == 0)
3343 return cached_result = msp430_mcu_data[i].hwmpy == 4;
3345 return cached_result = false;
3348 /* Returns true if the current MCU does not have a
3349 hardware multiplier of any kind. */
3351 static bool
3352 msp430_no_hwmult (void)
3354 static const char * cached_match = NULL;
3355 static bool cached_result;
3356 int i;
3358 if (msp430_hwmult_type == MSP430_HWMULT_NONE)
3359 return true;
3361 if (msp430_hwmult_type != MSP430_HWMULT_AUTO)
3362 return false;
3364 if (target_mcu == NULL)
3365 return true;
3367 if (target_mcu == cached_match)
3368 return cached_result;
3370 cached_match = target_mcu;
3372 /* FIXME: This array is alpha sorted - we could use a binary search. */
3373 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
3374 if (strcasecmp (target_mcu, msp430_mcu_data[i].name) == 0)
3375 return cached_result = msp430_mcu_data[i].hwmpy == 0;
3377 /* If we do not recognise the MCU name, we assume that it does not support
3378 any kind of hardware multiply - this is the safest assumption to make. */
3379 return cached_result = true;
3382 /* This function does the same as the default, but it will replace GCC
3383 function names with the MSPABI-specified ones. */
3385 void
3386 msp430_output_labelref (FILE *file, const char *name)
3388 int i;
3390 for (i = 0; helper_function_name_mappings [i].gcc_name; i++)
3391 if (strcmp (helper_function_name_mappings [i].gcc_name, name) == 0)
3393 name = helper_function_name_mappings [i].ti_name;
3394 break;
3397 /* If we have been given a specific MCU name then we may be
3398 able to make use of its hardware multiply capabilities. */
3399 if (msp430_hwmult_type != MSP430_HWMULT_NONE)
3401 if (strcmp ("__mspabi_mpyi", name) == 0)
3403 if (msp430_use_f5_series_hwmult ())
3404 name = "__mulhi2_f5";
3405 else if (! msp430_no_hwmult ())
3406 name = "__mulhi2";
3408 else if (strcmp ("__mspabi_mpyl", name) == 0)
3410 if (msp430_use_f5_series_hwmult ())
3411 name = "__mulsi2_f5";
3412 else if (use_32bit_hwmult ())
3413 name = "__mulsi2_hw32";
3414 else if (! msp430_no_hwmult ())
3415 name = "__mulsi2";
3419 fputs (name, file);
3422 /* Common code for msp430_print_operand... */
3424 static void
3425 msp430_print_operand_raw (FILE * file, rtx op)
3427 HOST_WIDE_INT i;
3429 switch (GET_CODE (op))
3431 case REG:
3432 fprintf (file, "%s", reg_names [REGNO (op)]);
3433 break;
3435 case CONST_INT:
3436 i = INTVAL (op);
3437 if (TARGET_ASM_HEX)
3438 fprintf (file, "%#" HOST_WIDE_INT_PRINT "x", i);
3439 else
3440 fprintf (file, "%" HOST_WIDE_INT_PRINT "d", i);
3441 break;
3443 case CONST:
3444 case PLUS:
3445 case MINUS:
3446 case SYMBOL_REF:
3447 case LABEL_REF:
3448 output_addr_const (file, op);
3449 break;
3451 default:
3452 print_rtl (file, op);
3453 break;
3457 #undef TARGET_PRINT_OPERAND_ADDRESS
3458 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
3460 /* Output to stdio stream FILE the assembler syntax for an
3461 instruction operand that is a memory reference whose address
3462 is ADDR. */
3464 static void
3465 msp430_print_operand_addr (FILE * file, machine_mode /*mode*/, rtx addr)
3467 switch (GET_CODE (addr))
3469 case PLUS:
3470 msp430_print_operand_raw (file, XEXP (addr, 1));
3471 gcc_assert (REG_P (XEXP (addr, 0)));
3472 fprintf (file, "(%s)", reg_names [REGNO (XEXP (addr, 0))]);
3473 return;
3475 case REG:
3476 fprintf (file, "@");
3477 break;
3479 case CONST:
3480 case CONST_INT:
3481 case SYMBOL_REF:
3482 case LABEL_REF:
3483 fprintf (file, "&");
3484 break;
3486 default:
3487 break;
3490 msp430_print_operand_raw (file, addr);
3493 #undef TARGET_PRINT_OPERAND
3494 #define TARGET_PRINT_OPERAND msp430_print_operand
3496 /* A low 16-bits of int/lower of register pair
3497 B high 16-bits of int/higher of register pair
3498 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
3499 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
3500 H like %B (for backwards compatibility)
3501 I inverse of value
3502 J an integer without a # prefix
3503 L like %A (for backwards compatibility)
3504 O offset of the top of the stack
3505 Q like X but generates an A postfix
3506 R inverse of condition code, unsigned.
3507 X X instruction postfix in large mode
3508 Y value - 4
3509 Z value - 1
3510 b .B or .W or .A, depending upon the mode
3511 p bit position
3512 r inverse of condition code
3513 x like X but only for pointers. */
3515 static void
3516 msp430_print_operand (FILE * file, rtx op, int letter)
3518 rtx addr;
3520 /* We can't use c, n, a, or l. */
3521 switch (letter)
3523 case 'Z':
3524 gcc_assert (CONST_INT_P (op));
3525 /* Print the constant value, less one. */
3526 fprintf (file, "#%ld", INTVAL (op) - 1);
3527 return;
3528 case 'Y':
3529 gcc_assert (CONST_INT_P (op));
3530 /* Print the constant value, less four. */
3531 fprintf (file, "#%ld", INTVAL (op) - 4);
3532 return;
3533 case 'I':
3534 if (GET_CODE (op) == CONST_INT)
3536 /* Inverse of constants */
3537 int i = INTVAL (op);
3538 fprintf (file, "%d", ~i);
3539 return;
3541 op = XEXP (op, 0);
3542 break;
3543 case 'r': /* Conditional jump where the condition is reversed. */
3544 switch (GET_CODE (op))
3546 case EQ: fprintf (file, "NE"); break;
3547 case NE: fprintf (file, "EQ"); break;
3548 case GEU: fprintf (file, "LO"); break;
3549 case LTU: fprintf (file, "HS"); break;
3550 case GE: fprintf (file, "L"); break;
3551 case LT: fprintf (file, "GE"); break;
3552 /* Assume these have reversed operands. */
3553 case GTU: fprintf (file, "HS"); break;
3554 case LEU: fprintf (file, "LO"); break;
3555 case GT: fprintf (file, "GE"); break;
3556 case LE: fprintf (file, "L"); break;
3557 default:
3558 msp430_print_operand_raw (file, op);
3559 break;
3561 return;
3562 case 'R': /* Conditional jump where the operands are reversed. */
3563 switch (GET_CODE (op))
3565 case GTU: fprintf (file, "LO"); break;
3566 case LEU: fprintf (file, "HS"); break;
3567 case GT: fprintf (file, "L"); break;
3568 case LE: fprintf (file, "GE"); break;
3569 default:
3570 msp430_print_operand_raw (file, op);
3571 break;
3573 return;
3574 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
3575 gcc_assert (CONST_INT_P (op));
3576 fprintf (file, "#%d", 1 << INTVAL (op));
3577 return;
3578 case 'b':
3579 switch (GET_MODE (op))
3581 case E_QImode: fprintf (file, ".B"); return;
3582 case E_HImode: fprintf (file, ".W"); return;
3583 case E_PSImode: fprintf (file, ".A"); return;
3584 case E_SImode: fprintf (file, ".A"); return;
3585 default:
3586 return;
3588 case 'A':
3589 case 'L': /* Low half. */
3590 switch (GET_CODE (op))
3592 case MEM:
3593 op = adjust_address (op, Pmode, 0);
3594 break;
3595 case REG:
3596 break;
3597 case CONST_INT:
3598 op = GEN_INT (INTVAL (op) & 0xffff);
3599 letter = 0;
3600 break;
3601 default:
3602 /* If you get here, figure out a test case :-) */
3603 gcc_unreachable ();
3605 break;
3606 case 'B':
3607 case 'H': /* high half */
3608 switch (GET_CODE (op))
3610 case MEM:
3611 op = adjust_address (op, Pmode, 2);
3612 break;
3613 case REG:
3614 op = gen_rtx_REG (Pmode, REGNO (op) + 1);
3615 break;
3616 case CONST_INT:
3617 op = GEN_INT (INTVAL (op) >> 16);
3618 letter = 0;
3619 break;
3620 default:
3621 /* If you get here, figure out a test case :-) */
3622 gcc_unreachable ();
3624 break;
3625 case 'C':
3626 switch (GET_CODE (op))
3628 case MEM:
3629 op = adjust_address (op, Pmode, 3);
3630 break;
3631 case REG:
3632 op = gen_rtx_REG (Pmode, REGNO (op) + 2);
3633 break;
3634 case CONST_INT:
3635 op = GEN_INT ((long long) INTVAL (op) >> 32);
3636 letter = 0;
3637 break;
3638 default:
3639 /* If you get here, figure out a test case :-) */
3640 gcc_unreachable ();
3642 break;
3643 case 'D':
3644 switch (GET_CODE (op))
3646 case MEM:
3647 op = adjust_address (op, Pmode, 4);
3648 break;
3649 case REG:
3650 op = gen_rtx_REG (Pmode, REGNO (op) + 3);
3651 break;
3652 case CONST_INT:
3653 op = GEN_INT ((long long) INTVAL (op) >> 48);
3654 letter = 0;
3655 break;
3656 default:
3657 /* If you get here, figure out a test case :-) */
3658 gcc_unreachable ();
3660 break;
3662 case 'X':
3663 /* This is used to turn, for example, an ADD opcode into an ADDX
3664 opcode when we're using 20-bit addresses. */
3665 if (TARGET_LARGE || GET_MODE (op) == PSImode)
3666 fprintf (file, "X");
3667 /* We don't care which operand we use, but we want 'X' in the MD
3668 file, so we do it this way. */
3669 return;
3671 case 'x':
3672 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
3673 if (GET_MODE (op) == PSImode)
3674 fprintf (file, "X");
3675 return;
3677 case 'Q':
3678 /* Likewise, for BR -> BRA. */
3679 if (TARGET_LARGE)
3680 fprintf (file, "A");
3681 return;
3683 case 'O':
3684 /* Computes the offset to the top of the stack for the current frame.
3685 This has to be done here rather than in, say, msp430_expand_builtin()
3686 because builtins are expanded before the frame layout is determined. */
3687 fprintf (file, "%d",
3688 msp430_initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM)
3689 - (TARGET_LARGE ? 4 : 2));
3690 return;
3692 case 'J':
3693 gcc_assert (GET_CODE (op) == CONST_INT);
3694 case 0:
3695 break;
3696 default:
3697 output_operand_lossage ("invalid operand prefix");
3698 return;
3701 switch (GET_CODE (op))
3703 case REG:
3704 msp430_print_operand_raw (file, op);
3705 break;
3707 case MEM:
3708 addr = XEXP (op, 0);
3709 msp430_print_operand_addr (file, GET_MODE (op), addr);
3710 break;
3712 case CONST:
3713 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTRACT)
3715 op = XEXP (op, 0);
3716 switch (INTVAL (XEXP (op, 2)))
3718 case 0:
3719 fprintf (file, "#lo (");
3720 msp430_print_operand_raw (file, XEXP (op, 0));
3721 fprintf (file, ")");
3722 break;
3724 case 16:
3725 fprintf (file, "#hi (");
3726 msp430_print_operand_raw (file, XEXP (op, 0));
3727 fprintf (file, ")");
3728 break;
3730 default:
3731 output_operand_lossage ("invalid zero extract");
3732 break;
3734 break;
3736 /* Fall through. */
3737 case CONST_INT:
3738 case SYMBOL_REF:
3739 case LABEL_REF:
3740 if (letter == 0)
3741 fprintf (file, "#");
3742 msp430_print_operand_raw (file, op);
3743 break;
3745 case EQ: fprintf (file, "EQ"); break;
3746 case NE: fprintf (file, "NE"); break;
3747 case GEU: fprintf (file, "HS"); break;
3748 case LTU: fprintf (file, "LO"); break;
3749 case GE: fprintf (file, "GE"); break;
3750 case LT: fprintf (file, "L"); break;
3752 default:
3753 print_rtl (file, op);
3754 break;
3759 /* Frame stuff. */
3762 msp430_return_addr_rtx (int count)
3764 int ra_size;
3765 if (count)
3766 return NULL_RTX;
3768 ra_size = TARGET_LARGE ? 4 : 2;
3769 if (crtl->args.pretend_args_size)
3770 ra_size += 2;
3772 return gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, arg_pointer_rtx, GEN_INT (- ra_size)));
3776 msp430_incoming_return_addr_rtx (void)
3778 return gen_rtx_MEM (Pmode, stack_pointer_rtx);
3781 /* Instruction generation stuff. */
3783 /* Generate a sequence of instructions to sign-extend an HI
3784 value into an SI value. Handles the tricky case where
3785 we are overwriting the destination. */
3787 const char *
3788 msp430x_extendhisi (rtx * operands)
3790 if (REGNO (operands[0]) == REGNO (operands[1]))
3791 /* Low word of dest == source word. */
3792 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
3794 if (! msp430x)
3795 /* Note: This sequence is approximately the same length as invoking a helper
3796 function to perform the sign-extension, as in:
3798 MOV.W %1, %L0
3799 MOV.W %1, r12
3800 CALL __mspabi_srai_15
3801 MOV.W r12, %H0
3803 but this version does not involve any function calls or using argument
3804 registers, so it reduces register pressure. */
3805 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
3807 if (REGNO (operands[0]) + 1 == REGNO (operands[1]))
3808 /* High word of dest == source word. */
3809 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
3811 /* No overlap between dest and source. */
3812 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
3815 /* Likewise for logical right shifts. */
3816 const char *
3817 msp430x_logical_shift_right (rtx amount)
3819 /* The MSP430X's logical right shift instruction - RRUM - does
3820 not use an extension word, so we cannot encode a repeat count.
3821 Try various alternatives to work around this. If the count
3822 is in a register we are stuck, hence the assert. */
3823 gcc_assert (CONST_INT_P (amount));
3825 if (INTVAL (amount) <= 0
3826 || INTVAL (amount) >= 16)
3827 return "# nop logical shift.";
3829 if (INTVAL (amount) > 0
3830 && INTVAL (amount) < 5)
3831 return "rrum.w\t%2, %0"; /* Two bytes. */
3833 if (INTVAL (amount) > 4
3834 && INTVAL (amount) < 9)
3835 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
3837 /* First we logically shift right by one. Now we know
3838 that the top bit is zero and we can use the arithmetic
3839 right shift instruction to perform the rest of the shift. */
3840 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
3843 /* Stop GCC from thinking that it can eliminate (SUBREG:PSI (SI)). */
3845 #undef TARGET_CAN_CHANGE_MODE_CLASS
3846 #define TARGET_CAN_CHANGE_MODE_CLASS msp430_can_change_mode_class
3848 static bool
3849 msp430_can_change_mode_class (machine_mode from, machine_mode to, reg_class_t)
3851 if ((to == PSImode && from == SImode)
3852 || (to == SImode && from == PSImode)
3853 || (to == DImode && from == PSImode)
3854 || (to == PSImode && from == DImode))
3855 return false;
3856 return true;
3859 struct gcc_target targetm = TARGET_INITIALIZER;
3861 #include "gt-msp430.h"