re PR target/87927 (ICE: segmentation fault with patchable_function_entry attribute...
[official-gcc.git] / gcc / config / msp430 / msp430.c
blob3a41cc011e7516f25f244bb724cfb7fd800b81b3
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 unsigned int start_upper;
729 unsigned int end_upper;
730 static char mcu_name[64];
732 /* The 'i' in the device name symbol for msp430i* devices must be lower
733 case, to match the expected symbol in msp430.h. */
734 if (strncmp (target_mcu, "msp430i", 7) == 0)
736 snprintf (mcu_name, sizeof (mcu_name) - 1, "__MSP430i%s__",
737 target_mcu + 7);
738 start_upper = 9;
740 else
742 snprintf (mcu_name, sizeof (mcu_name) - 1, "__%s__", target_mcu);
743 start_upper = 2;
745 end_upper = strlen (mcu_name) - 2;
746 for (i = start_upper; i < end_upper; i++)
747 mcu_name[i] = TOUPPER (mcu_name[i]);
748 return mcu_name;
751 return msp430x ? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
754 static const char *
755 hwmult_name (unsigned int val)
757 switch (val)
759 case 0: return "none";
760 case 1: return "16-bit";
761 case 2: return "16-bit";
762 case 4: return "32-bit";
763 case 8: return "32-bit (5xx)";
764 default: gcc_unreachable ();
768 static void
769 msp430_option_override (void)
771 /* The MSP430 architecture can safely dereference a NULL pointer. In fact,
772 there are memory mapped registers there. */
773 flag_delete_null_pointer_checks = 0;
775 init_machine_status = msp430_init_machine_status;
777 if (target_cpu)
779 /* gcc/common/config/msp430-common.c will have
780 already canonicalised the string in target_cpu. */
781 if (strcasecmp (target_cpu, "msp430x") == 0)
782 msp430x = true;
783 else /* target_cpu == "msp430" - already handled by the front end. */
784 msp430x = false;
787 if (target_mcu)
789 int i;
791 /* FIXME: If the array were alpha sorted, we could use a binary search. */
792 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
793 if (strcasecmp (msp430_mcu_data[i].name, target_mcu) == 0)
795 bool xisa = msp430_mcu_data[i].revision >= 1;
797 if (msp430_warn_mcu)
799 if (target_cpu&& msp430x != xisa)
800 warning (0, "MCU '%s' supports %s ISA but -mcpu option is set to %s",
801 target_mcu, xisa ? "430X" : "430", msp430x ? "430X" : "430");
803 if (msp430_mcu_data[i].hwmpy == 0
804 && msp430_hwmult_type != MSP430_HWMULT_AUTO
805 && msp430_hwmult_type != MSP430_HWMULT_NONE)
806 warning (0, "MCU '%s' does not have hardware multiply support, but -mhwmult is set to %s",
807 target_mcu,
808 msp430_hwmult_type == MSP430_HWMULT_SMALL ? "16-bit"
809 : msp430_hwmult_type == MSP430_HWMULT_LARGE ? "32-bit" : "f5series");
810 else if (msp430_hwmult_type == MSP430_HWMULT_SMALL
811 && msp430_mcu_data[i].hwmpy != 1
812 && msp430_mcu_data[i].hwmpy != 2 )
813 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to 16-bit",
814 target_mcu, hwmult_name (msp430_mcu_data[i].hwmpy));
815 else if (msp430_hwmult_type == MSP430_HWMULT_LARGE && msp430_mcu_data[i].hwmpy != 4)
816 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to 32-bit",
817 target_mcu, hwmult_name (msp430_mcu_data[i].hwmpy));
818 else if (msp430_hwmult_type == MSP430_HWMULT_F5SERIES && msp430_mcu_data[i].hwmpy != 8)
819 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to f5series",
820 target_mcu, hwmult_name (msp430_mcu_data[i].hwmpy));
823 msp430x = xisa;
824 break;
827 if (i < 0)
829 if (msp430_hwmult_type == MSP430_HWMULT_AUTO)
831 if (msp430_warn_mcu)
833 if (target_cpu == NULL)
834 warning (0,
835 "Unrecognized MCU name '%s', assuming that it is "
836 "just a MSP430 with no hardware multiply.\n"
837 "Use the -mcpu and -mhwmult options to set "
838 "these explicitly.",
839 target_mcu);
840 else
841 warning (0,
842 "Unrecognized MCU name '%s', assuming that it "
843 "has no hardware multiply.\nUse the -mhwmult "
844 "option to set this explicitly.",
845 target_mcu);
848 msp430_hwmult_type = MSP430_HWMULT_NONE;
850 else if (target_cpu == NULL)
852 if (msp430_warn_mcu)
853 warning (0,
854 "Unrecognized MCU name '%s', assuming that it just "
855 "supports the MSP430 ISA.\nUse the -mcpu option to "
856 "set the ISA explicitly.",
857 target_mcu);
859 msp430x = false;
861 else if (msp430_warn_mcu)
862 warning (0, "Unrecognized MCU name '%s'.", target_mcu);
866 /* The F5 series are all able to support the 430X ISA. */
867 if (target_cpu == NULL && target_mcu == NULL && msp430_hwmult_type == MSP430_HWMULT_F5SERIES)
868 msp430x = true;
870 if (TARGET_LARGE && !msp430x)
871 error ("-mlarge requires a 430X-compatible -mmcu=");
873 if (msp430_code_region == MSP430_REGION_UPPER && ! msp430x)
874 error ("-mcode-region=upper requires 430X-compatible cpu");
875 if (msp430_data_region == MSP430_REGION_UPPER && ! msp430x)
876 error ("-mdata-region=upper requires 430X-compatible cpu");
878 if (flag_exceptions || flag_non_call_exceptions
879 || flag_unwind_tables || flag_asynchronous_unwind_tables)
880 flag_omit_frame_pointer = false;
881 else
882 flag_omit_frame_pointer = true;
884 /* This is a hack to work around a problem with the newlib build
885 mechanism. Newlib always appends CFLAGS to the end of the GCC
886 command line and always sets -O2 in CFLAGS. Thus it is not
887 possible to build newlib with -Os enabled. Until now... */
888 if (TARGET_OPT_SPACE && optimize < 3)
889 optimize_size = 1;
892 #undef TARGET_SCALAR_MODE_SUPPORTED_P
893 #define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
895 static bool
896 msp430_scalar_mode_supported_p (scalar_mode m)
898 if (m == PSImode && msp430x)
899 return true;
900 #if 0
901 if (m == TImode)
902 return true;
903 #endif
904 return default_scalar_mode_supported_p (m);
909 /* Storage Layout */
911 #undef TARGET_MS_BITFIELD_LAYOUT_P
912 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
914 bool
915 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED)
917 return false;
922 /* Register Usage */
924 #undef TARGET_HARD_REGNO_NREGS
925 #define TARGET_HARD_REGNO_NREGS msp430_hard_regno_nregs
927 static unsigned int
928 msp430_hard_regno_nregs (unsigned int, machine_mode mode)
930 if (mode == PSImode && msp430x)
931 return 1;
932 if (mode == CPSImode && msp430x)
933 return 2;
934 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
935 / UNITS_PER_WORD);
938 /* Implements HARD_REGNO_NREGS_HAS_PADDING. */
940 msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED,
941 machine_mode mode)
943 if (mode == PSImode && msp430x)
944 return 1;
945 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
946 / UNITS_PER_WORD);
949 /* Implements HARD_REGNO_NREGS_WITH_PADDING. */
951 msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED,
952 machine_mode mode)
954 if (mode == PSImode)
955 return 2;
956 if (mode == CPSImode)
957 return 4;
958 return msp430_hard_regno_nregs (regno, mode);
961 #undef TARGET_HARD_REGNO_MODE_OK
962 #define TARGET_HARD_REGNO_MODE_OK msp430_hard_regno_mode_ok
964 static bool
965 msp430_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
967 return regno <= (ARG_POINTER_REGNUM
968 - (unsigned int) msp430_hard_regno_nregs (regno, mode));
971 #undef TARGET_MODES_TIEABLE_P
972 #define TARGET_MODES_TIEABLE_P msp430_modes_tieable_p
974 static bool
975 msp430_modes_tieable_p (machine_mode mode1, machine_mode mode2)
977 if ((mode1 == PSImode || mode2 == SImode)
978 || (mode1 == SImode || mode2 == PSImode))
979 return false;
981 return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
982 || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
983 == (GET_MODE_CLASS (mode2) == MODE_FLOAT
984 || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
987 #undef TARGET_FRAME_POINTER_REQUIRED
988 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
990 static bool
991 msp430_frame_pointer_required (void)
993 return false;
996 #undef TARGET_CAN_ELIMINATE
997 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
999 static bool
1000 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED,
1001 const int to_reg ATTRIBUTE_UNUSED)
1003 return true;
1006 /* Implements INITIAL_ELIMINATION_OFFSET. */
1008 msp430_initial_elimination_offset (int from, int to)
1010 int rv = 0; /* As if arg to arg. */
1012 msp430_compute_frame_info ();
1014 switch (to)
1016 case STACK_POINTER_REGNUM:
1017 rv += cfun->machine->framesize_outgoing;
1018 rv += cfun->machine->framesize_locals;
1019 /* Fall through. */
1020 case FRAME_POINTER_REGNUM:
1021 rv += cfun->machine->framesize_regs;
1022 /* Allow for the saved return address. */
1023 rv += (TARGET_LARGE ? 4 : 2);
1024 /* NB/ No need to allow for crtl->args.pretend_args_size.
1025 GCC does that for us. */
1026 break;
1027 default:
1028 gcc_unreachable ();
1031 switch (from)
1033 case FRAME_POINTER_REGNUM:
1034 /* Allow for the fall through above. */
1035 rv -= (TARGET_LARGE ? 4 : 2);
1036 rv -= cfun->machine->framesize_regs;
1037 case ARG_POINTER_REGNUM:
1038 break;
1039 default:
1040 gcc_unreachable ();
1043 return rv;
1046 /* Named Address Space support */
1049 /* Return the appropriate mode for a named address pointer. */
1050 #undef TARGET_ADDR_SPACE_POINTER_MODE
1051 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
1052 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
1053 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
1055 static scalar_int_mode
1056 msp430_addr_space_pointer_mode (addr_space_t addrspace)
1058 switch (addrspace)
1060 default:
1061 case ADDR_SPACE_GENERIC:
1062 return Pmode;
1063 case ADDR_SPACE_NEAR:
1064 return HImode;
1065 case ADDR_SPACE_FAR:
1066 return PSImode;
1070 /* Function pointers are stored in unwind_word sized
1071 variables, so make sure that unwind_word is big enough. */
1072 #undef TARGET_UNWIND_WORD_MODE
1073 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
1075 static scalar_int_mode
1076 msp430_unwind_word_mode (void)
1078 /* This needs to match msp430_init_dwarf_reg_sizes_extra (below). */
1079 return msp430x ? PSImode : HImode;
1082 /* Determine if one named address space is a subset of another. */
1083 #undef TARGET_ADDR_SPACE_SUBSET_P
1084 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
1085 static bool
1086 msp430_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
1088 if (subset == superset)
1089 return true;
1090 else
1091 return (subset != ADDR_SPACE_FAR && superset == ADDR_SPACE_FAR);
1094 #undef TARGET_ADDR_SPACE_CONVERT
1095 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
1096 /* Convert from one address space to another. */
1097 static rtx
1098 msp430_addr_space_convert (rtx op, tree from_type, tree to_type)
1100 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
1101 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
1102 rtx result;
1104 if (to_as != ADDR_SPACE_FAR && from_as == ADDR_SPACE_FAR)
1106 /* This is unpredictable, as we're truncating off usable address
1107 bits. */
1109 if (CONSTANT_P (op))
1110 return gen_rtx_CONST (HImode, op);
1112 result = gen_reg_rtx (HImode);
1113 emit_insn (gen_truncpsihi2 (result, op));
1114 return result;
1116 else if (to_as == ADDR_SPACE_FAR && from_as != ADDR_SPACE_FAR)
1118 /* This always works. */
1120 if (CONSTANT_P (op))
1121 return gen_rtx_CONST (PSImode, op);
1123 result = gen_reg_rtx (PSImode);
1124 emit_insn (gen_zero_extendhipsi2 (result, op));
1125 return result;
1127 else
1128 gcc_unreachable ();
1131 /* Stack Layout and Calling Conventions. */
1133 /* For each function, we list the gcc version and the TI version on
1134 each line, where we're converting the function names. */
1135 static char const * const special_convention_function_names [] =
1137 "__muldi3", "__mspabi_mpyll",
1138 "__udivdi3", "__mspabi_divull",
1139 "__umoddi3", "__mspabi_remull",
1140 "__divdi3", "__mspabi_divlli",
1141 "__moddi3", "__mspabi_remlli",
1142 "__mspabi_srall",
1143 "__mspabi_srlll",
1144 "__mspabi_sllll",
1145 "__adddf3", "__mspabi_addd",
1146 "__subdf3", "__mspabi_subd",
1147 "__muldf3", "__mspabi_mpyd",
1148 "__divdf3", "__mspabi_divd",
1149 "__mspabi_cmpd",
1150 NULL
1153 /* TRUE if the function passed is a "speical" function. Special
1154 functions pass two DImode parameters in registers. */
1155 static bool
1156 msp430_special_register_convention_p (const char *name)
1158 int i;
1160 for (i = 0; special_convention_function_names [i]; i++)
1161 if (! strcmp (name, special_convention_function_names [i]))
1162 return true;
1164 return false;
1167 #undef TARGET_FUNCTION_VALUE_REGNO_P
1168 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
1170 bool
1171 msp430_function_value_regno_p (unsigned int regno)
1173 return regno == 12;
1177 #undef TARGET_FUNCTION_VALUE
1178 #define TARGET_FUNCTION_VALUE msp430_function_value
1181 msp430_function_value (const_tree ret_type,
1182 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1183 bool outgoing ATTRIBUTE_UNUSED)
1185 return gen_rtx_REG (TYPE_MODE (ret_type), 12);
1188 #undef TARGET_LIBCALL_VALUE
1189 #define TARGET_LIBCALL_VALUE msp430_libcall_value
1192 msp430_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
1194 return gen_rtx_REG (mode, 12);
1197 /* Implements INIT_CUMULATIVE_ARGS. */
1198 void
1199 msp430_init_cumulative_args (CUMULATIVE_ARGS *ca,
1200 tree fntype ATTRIBUTE_UNUSED,
1201 rtx libname ATTRIBUTE_UNUSED,
1202 tree fndecl ATTRIBUTE_UNUSED,
1203 int n_named_args ATTRIBUTE_UNUSED)
1205 const char *fname;
1206 memset (ca, 0, sizeof(*ca));
1208 ca->can_split = 1;
1210 if (fndecl)
1211 fname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
1212 else if (libname)
1213 fname = XSTR (libname, 0);
1214 else
1215 fname = NULL;
1217 if (fname && msp430_special_register_convention_p (fname))
1218 ca->special_p = 1;
1221 /* Helper function for argument passing; this function is the common
1222 code that determines where an argument will be passed. */
1223 static void
1224 msp430_evaluate_arg (cumulative_args_t cap,
1225 machine_mode mode,
1226 const_tree type ATTRIBUTE_UNUSED,
1227 bool named)
1229 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1230 int nregs = GET_MODE_SIZE (mode);
1231 int i;
1233 ca->reg_count = 0;
1234 ca->mem_count = 0;
1236 if (!named)
1237 return;
1239 if (mode == PSImode)
1240 nregs = 1;
1241 else
1242 nregs = (nregs + 1) / 2;
1244 if (ca->special_p)
1246 /* Function is passed two DImode operands, in R8:R11 and
1247 R12:15. */
1248 ca->start_reg = 8;
1249 ca->reg_count = 4;
1250 return;
1253 switch (nregs)
1255 case 1:
1256 for (i = 0; i < 4; i++)
1257 if (! ca->reg_used [i])
1259 ca->reg_count = 1;
1260 ca->start_reg = CA_FIRST_REG + i;
1261 return;
1263 break;
1264 case 2:
1265 for (i = 0; i < 3; i++)
1266 if (! ca->reg_used [i] && ! ca->reg_used [i + 1])
1268 ca->reg_count = 2;
1269 ca->start_reg = CA_FIRST_REG + i;
1270 return;
1272 if (! ca->reg_used [3] && ca->can_split)
1274 ca->reg_count = 1;
1275 ca->mem_count = 2;
1276 ca->start_reg = CA_FIRST_REG + 3;
1277 return;
1279 break;
1280 case 3:
1281 case 4:
1282 ca->can_split = 0;
1283 if (! ca->reg_used [0]
1284 && ! ca->reg_used [1]
1285 && ! ca->reg_used [2]
1286 && ! ca->reg_used [3])
1288 ca->reg_count = 4;
1289 ca->start_reg = CA_FIRST_REG;
1290 return;
1292 break;
1296 #undef TARGET_PROMOTE_PROTOTYPES
1297 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
1299 bool
1300 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED)
1302 return false;
1305 #undef TARGET_FUNCTION_ARG
1306 #define TARGET_FUNCTION_ARG msp430_function_arg
1309 msp430_function_arg (cumulative_args_t cap,
1310 machine_mode mode,
1311 const_tree type,
1312 bool named)
1314 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1316 msp430_evaluate_arg (cap, mode, type, named);
1318 if (ca->reg_count)
1319 return gen_rtx_REG (mode, ca->start_reg);
1321 return 0;
1324 #undef TARGET_ARG_PARTIAL_BYTES
1325 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
1328 msp430_arg_partial_bytes (cumulative_args_t cap,
1329 machine_mode mode,
1330 tree type,
1331 bool named)
1333 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1335 msp430_evaluate_arg (cap, mode, type, named);
1337 if (ca->reg_count && ca->mem_count)
1338 return ca->reg_count * UNITS_PER_WORD;
1340 return 0;
1343 #undef TARGET_PASS_BY_REFERENCE
1344 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
1346 static bool
1347 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED,
1348 machine_mode mode,
1349 const_tree type,
1350 bool named ATTRIBUTE_UNUSED)
1352 return (mode == BLKmode
1353 || (type && TREE_CODE (type) == RECORD_TYPE)
1354 || (type && TREE_CODE (type) == UNION_TYPE));
1357 #undef TARGET_CALLEE_COPIES
1358 #define TARGET_CALLEE_COPIES msp430_callee_copies
1360 static bool
1361 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED,
1362 machine_mode mode ATTRIBUTE_UNUSED,
1363 const_tree type ATTRIBUTE_UNUSED,
1364 bool named ATTRIBUTE_UNUSED)
1366 return true;
1369 #undef TARGET_FUNCTION_ARG_ADVANCE
1370 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
1372 void
1373 msp430_function_arg_advance (cumulative_args_t cap,
1374 machine_mode mode,
1375 const_tree type,
1376 bool named)
1378 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1379 int i;
1381 msp430_evaluate_arg (cap, mode, type, named);
1383 if (ca->start_reg >= CA_FIRST_REG)
1384 for (i = 0; i < ca->reg_count; i ++)
1385 ca->reg_used [i + ca->start_reg - CA_FIRST_REG] = 1;
1387 ca->special_p = 0;
1390 #undef TARGET_FUNCTION_ARG_BOUNDARY
1391 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
1393 static unsigned int
1394 msp430_function_arg_boundary (machine_mode mode, const_tree type)
1396 if (mode == BLKmode
1397 && int_size_in_bytes (type) > 1)
1398 return 16;
1399 if (GET_MODE_BITSIZE (mode) > 8)
1400 return 16;
1401 return 8;
1404 #undef TARGET_RETURN_IN_MEMORY
1405 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
1407 static bool
1408 msp430_return_in_memory (const_tree ret_type, const_tree fntype ATTRIBUTE_UNUSED)
1410 machine_mode mode = TYPE_MODE (ret_type);
1412 if (mode == BLKmode
1413 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == RECORD_TYPE)
1414 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == UNION_TYPE))
1415 return true;
1417 if (GET_MODE_SIZE (mode) > 8)
1418 return true;
1420 return false;
1423 #undef TARGET_GET_RAW_ARG_MODE
1424 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
1426 static fixed_size_mode
1427 msp430_get_raw_arg_mode (int regno)
1429 return as_a <fixed_size_mode> (regno == ARG_POINTER_REGNUM
1430 ? VOIDmode : Pmode);
1433 #undef TARGET_GET_RAW_RESULT_MODE
1434 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
1436 static fixed_size_mode
1437 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED)
1439 return Pmode;
1442 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
1443 #define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
1445 #include "gimplify.h"
1447 static tree
1448 msp430_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
1449 gimple_seq *post_p)
1451 tree addr, t, type_size, rounded_size, valist_tmp;
1452 unsigned HOST_WIDE_INT align, boundary;
1453 bool indirect;
1455 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
1456 if (indirect)
1457 type = build_pointer_type (type);
1459 align = PARM_BOUNDARY / BITS_PER_UNIT;
1460 boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
1462 /* When we align parameter on stack for caller, if the parameter
1463 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
1464 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
1465 here with caller. */
1466 if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
1467 boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
1469 boundary /= BITS_PER_UNIT;
1471 /* Hoist the valist value into a temporary for the moment. */
1472 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
1474 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
1475 requires greater alignment, we must perform dynamic alignment. */
1476 if (boundary > align
1477 && !integer_zerop (TYPE_SIZE (type)))
1479 /* FIXME: This is where this function diverts from targhooks.c:
1480 std_gimplify_va_arg_expr(). It works, but I do not know why... */
1481 if (! POINTER_TYPE_P (type))
1483 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
1484 fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
1485 gimplify_and_add (t, pre_p);
1487 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
1488 fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
1489 valist_tmp,
1490 build_int_cst (TREE_TYPE (valist), -boundary)));
1491 gimplify_and_add (t, pre_p);
1494 else
1495 boundary = align;
1497 /* If the actual alignment is less than the alignment of the type,
1498 adjust the type accordingly so that we don't assume strict alignment
1499 when dereferencing the pointer. */
1500 boundary *= BITS_PER_UNIT;
1501 if (boundary < TYPE_ALIGN (type))
1503 type = build_variant_type_copy (type);
1504 SET_TYPE_ALIGN (type, boundary);
1507 /* Compute the rounded size of the type. */
1508 type_size = size_in_bytes (type);
1509 rounded_size = round_up (type_size, align);
1511 /* Reduce rounded_size so it's sharable with the postqueue. */
1512 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
1514 /* Get AP. */
1515 addr = valist_tmp;
1517 /* Compute new value for AP. */
1518 t = fold_build_pointer_plus (valist_tmp, rounded_size);
1519 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
1520 gimplify_and_add (t, pre_p);
1522 addr = fold_convert (build_pointer_type (type), addr);
1524 if (indirect)
1525 addr = build_va_arg_indirect_ref (addr);
1527 addr = build_va_arg_indirect_ref (addr);
1529 return addr;
1532 #undef TARGET_LRA_P
1533 #define TARGET_LRA_P hook_bool_void_false
1535 /* Addressing Modes */
1537 #undef TARGET_LEGITIMATE_ADDRESS_P
1538 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
1540 static bool
1541 reg_ok_for_addr (rtx r, bool strict)
1543 int rn = REGNO (r);
1545 if (strict && rn >= FIRST_PSEUDO_REGISTER)
1546 rn = reg_renumber [rn];
1547 if (strict && 0 <= rn && rn < FIRST_PSEUDO_REGISTER)
1548 return true;
1549 if (!strict)
1550 return true;
1551 return false;
1554 bool
1555 msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
1556 rtx x ATTRIBUTE_UNUSED,
1557 bool strict ATTRIBUTE_UNUSED)
1559 switch (GET_CODE (x))
1561 case MEM:
1562 return false;
1564 case PLUS:
1565 if (REG_P (XEXP (x, 0)))
1567 if (GET_MODE (x) != GET_MODE (XEXP (x, 0)))
1568 return false;
1569 if (!reg_ok_for_addr (XEXP (x, 0), strict))
1570 return false;
1571 switch (GET_CODE (XEXP (x, 1)))
1573 case CONST:
1574 case SYMBOL_REF:
1575 case CONST_INT:
1576 return true;
1577 default:
1578 return false;
1581 return false;
1583 case REG:
1584 if (!reg_ok_for_addr (x, strict))
1585 return false;
1586 /* FALLTHRU */
1587 case CONST:
1588 case SYMBOL_REF:
1589 case CONST_INT:
1590 return true;
1592 default:
1593 return false;
1597 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1598 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
1600 bool
1601 msp430_addr_space_legitimate_address_p (machine_mode mode,
1602 rtx x,
1603 bool strict,
1604 addr_space_t as ATTRIBUTE_UNUSED)
1606 return msp430_legitimate_address_p (mode, x, strict);
1609 #undef TARGET_ASM_INTEGER
1610 #define TARGET_ASM_INTEGER msp430_asm_integer
1611 static bool
1612 msp430_asm_integer (rtx x, unsigned int size, int aligned_p)
1614 int c = GET_CODE (x);
1616 if (size == 3 && GET_MODE (x) == PSImode)
1617 size = 4;
1619 switch (size)
1621 case 4:
1622 if (c == SYMBOL_REF || c == CONST || c == LABEL_REF || c == CONST_INT
1623 || c == PLUS || c == MINUS)
1625 fprintf (asm_out_file, "\t.long\t");
1626 output_addr_const (asm_out_file, x);
1627 fputc ('\n', asm_out_file);
1628 return true;
1630 break;
1632 return default_assemble_integer (x, size, aligned_p);
1635 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
1636 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra
1637 static bool
1638 msp430_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED, rtx x)
1640 debug_rtx(x);
1641 return false;
1644 #undef TARGET_LEGITIMATE_CONSTANT_P
1645 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
1647 static bool
1648 msp430_legitimate_constant (machine_mode mode, rtx x)
1650 return ! CONST_INT_P (x)
1651 || mode != PSImode
1652 /* GCC does not know the width of the PSImode, so make
1653 sure that it does not try to use a constant value that
1654 is out of range. */
1655 || (INTVAL (x) < (1 << 20) && INTVAL (x) >= (HOST_WIDE_INT)(HOST_WIDE_INT_M1U << 20));
1659 #undef TARGET_RTX_COSTS
1660 #define TARGET_RTX_COSTS msp430_rtx_costs
1662 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED,
1663 machine_mode mode,
1664 int outer_code ATTRIBUTE_UNUSED,
1665 int opno ATTRIBUTE_UNUSED,
1666 int * total,
1667 bool speed ATTRIBUTE_UNUSED)
1669 int code = GET_CODE (x);
1671 switch (code)
1673 case SIGN_EXTEND:
1674 if (mode == SImode && outer_code == SET)
1676 *total = COSTS_N_INSNS (4);
1677 return true;
1679 break;
1680 case ASHIFT:
1681 case ASHIFTRT:
1682 case LSHIFTRT:
1683 if (!msp430x)
1685 *total = COSTS_N_INSNS (100);
1686 return true;
1688 break;
1690 return false;
1693 /* Function Entry and Exit */
1695 /* The MSP430 call frame looks like this:
1697 <higher addresses>
1698 +--------------------+
1700 | Stack Arguments |
1702 +--------------------+ <-- "arg pointer"
1704 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
1706 +--------------------+
1707 | SR if this func has|
1708 | been called via an |
1709 | interrupt. |
1710 +--------------------+ <-- SP before prologue, also AP
1712 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
1714 +--------------------+ <-- "frame pointer"
1716 | Locals |
1718 +--------------------+
1720 | Outgoing Args |
1722 +--------------------+ <-- SP during function
1723 <lower addresses>
1727 /* We use this to wrap all emitted insns in the prologue, so they get
1728 the "frame-related" (/f) flag set. */
1729 static rtx
1730 F (rtx x)
1732 RTX_FRAME_RELATED_P (x) = 1;
1733 return x;
1736 /* This is the one spot that decides if a register is to be saved and
1737 restored in the prologue/epilogue. */
1738 static bool
1739 msp430_preserve_reg_p (int regno)
1741 /* PC, SP, SR, and the constant generator. */
1742 if (regno <= 3)
1743 return false;
1745 /* FIXME: add interrupt, EH, etc. */
1746 if (crtl->calls_eh_return)
1747 return true;
1749 /* Shouldn't be more than the above, but just in case... */
1750 if (fixed_regs [regno])
1751 return false;
1753 /* Interrupt handlers save all registers they use, even
1754 ones which are call saved. If they call other functions
1755 then *every* register is saved. */
1756 if (msp430_is_interrupt_func ())
1757 return ! crtl->is_leaf || df_regs_ever_live_p (regno);
1759 if (!call_used_regs [regno]
1760 && df_regs_ever_live_p (regno))
1761 return true;
1763 return false;
1766 /* Compute all the frame-related fields in our machine_function
1767 structure. */
1768 static void
1769 msp430_compute_frame_info (void)
1771 int i;
1773 cfun->machine->computed = 1;
1774 cfun->machine->framesize_regs = 0;
1775 cfun->machine->framesize_locals = get_frame_size ();
1776 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
1778 for (i = 0; i < ARG_POINTER_REGNUM; i ++)
1779 if (msp430_preserve_reg_p (i))
1781 cfun->machine->need_to_save [i] = 1;
1782 cfun->machine->framesize_regs += (TARGET_LARGE ? 4 : 2);
1784 else
1785 cfun->machine->need_to_save [i] = 0;
1787 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
1788 cfun->machine->framesize_locals ++;
1790 cfun->machine->framesize = (cfun->machine->framesize_regs
1791 + cfun->machine->framesize_locals
1792 + cfun->machine->framesize_outgoing);
1795 /* Attribute Handling. */
1797 const char * const ATTR_INTR = "interrupt";
1798 const char * const ATTR_WAKEUP = "wakeup";
1799 const char * const ATTR_NAKED = "naked";
1800 const char * const ATTR_REENT = "reentrant";
1801 const char * const ATTR_CRIT = "critical";
1802 const char * const ATTR_LOWER = "lower";
1803 const char * const ATTR_UPPER = "upper";
1804 const char * const ATTR_EITHER = "either";
1805 const char * const ATTR_NOINIT = "noinit";
1806 const char * const ATTR_PERSIST = "persistent";
1808 static inline bool
1809 has_attr (const char * attr, tree decl)
1811 if (decl == NULL_TREE)
1812 return false;
1813 return lookup_attribute (attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
1816 static bool
1817 is_interrupt_func (tree decl = current_function_decl)
1819 return has_attr (ATTR_INTR, decl);
1822 /* Returns true if the current function has the "interrupt" attribute. */
1824 bool
1825 msp430_is_interrupt_func (void)
1827 return is_interrupt_func (current_function_decl);
1830 static bool
1831 is_wakeup_func (tree decl = current_function_decl)
1833 return is_interrupt_func (decl) && has_attr (ATTR_WAKEUP, decl);
1836 static inline bool
1837 is_naked_func (tree decl = current_function_decl)
1839 return has_attr (ATTR_NAKED, decl);
1842 static inline bool
1843 is_reentrant_func (tree decl = current_function_decl)
1845 return has_attr (ATTR_REENT, decl);
1848 static inline bool
1849 is_critical_func (tree decl = current_function_decl)
1851 return has_attr (ATTR_CRIT, decl);
1854 static bool
1855 has_section_name (const char * name, tree decl = current_function_decl)
1857 if (decl == NULL_TREE)
1858 return false;
1859 return (DECL_SECTION_NAME (decl)
1860 && (strcmp (name, DECL_SECTION_NAME (decl)) == 0));
1863 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
1864 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS msp430_allocate_stack_slots_for_args
1866 static bool
1867 msp430_allocate_stack_slots_for_args (void)
1869 /* Naked functions should not allocate stack slots for arguments. */
1870 return ! is_naked_func ();
1873 #undef TARGET_WARN_FUNC_RETURN
1874 #define TARGET_WARN_FUNC_RETURN msp430_warn_func_return
1876 static bool
1877 msp430_warn_func_return (tree decl)
1879 /* Naked functions are implemented entirely in assembly, including the
1880 return sequence, so suppress warnings about this. */
1881 return !is_naked_func (decl);
1884 /* Verify MSP430 specific attributes. */
1885 #define TREE_NAME_EQ(NAME, STR) (strcmp (IDENTIFIER_POINTER (NAME), (STR)) == 0)
1887 static tree
1888 msp430_attr (tree * node,
1889 tree name,
1890 tree args,
1891 int flags ATTRIBUTE_UNUSED,
1892 bool * no_add_attrs)
1894 gcc_assert (DECL_P (* node));
1896 /* Only the interrupt attribute takes an argument. */
1897 if (args != NULL)
1899 tree value = TREE_VALUE (args);
1901 switch (TREE_CODE (value))
1903 case STRING_CST:
1904 if ( strcmp (TREE_STRING_POINTER (value), "reset")
1905 && strcmp (TREE_STRING_POINTER (value), "nmi")
1906 && strcmp (TREE_STRING_POINTER (value), "watchdog"))
1907 /* Allow the attribute to be added - the linker script
1908 being used may still recognise this name. */
1909 warning (OPT_Wattributes,
1910 "unrecognized interrupt vector argument of %qE attribute",
1911 name);
1912 break;
1914 case INTEGER_CST:
1915 if (wi::gtu_p (wi::to_wide (value), 63))
1916 /* Allow the attribute to be added - the linker script
1917 being used may still recognise this value. */
1918 warning (OPT_Wattributes,
1919 "numeric argument of %qE attribute must be in range 0..63",
1920 name);
1921 break;
1923 default:
1924 warning (OPT_Wattributes,
1925 "argument of %qE attribute is not a string constant or number",
1926 name);
1927 *no_add_attrs = true;
1928 break;
1932 const char * message = NULL;
1934 if (TREE_CODE (* node) != FUNCTION_DECL)
1936 message = "%qE attribute only applies to functions";
1938 else if (TREE_NAME_EQ (name, ATTR_INTR))
1940 if (TREE_CODE (TREE_TYPE (* node)) == FUNCTION_TYPE
1941 && ! VOID_TYPE_P (TREE_TYPE (TREE_TYPE (* node))))
1942 message = "interrupt handlers must be void";
1943 else
1945 /* Ensure interrupt handlers never get optimised out. */
1946 TREE_USED (* node) = 1;
1947 DECL_PRESERVE_P (* node) = 1;
1950 else if (TREE_NAME_EQ (name, ATTR_REENT))
1952 if (is_naked_func (* node))
1953 message = "naked functions cannot be reentrant";
1954 else if (is_critical_func (* node))
1955 message = "critical functions cannot be reentrant";
1957 else if (TREE_NAME_EQ (name, ATTR_CRIT))
1959 if (is_naked_func (* node))
1960 message = "naked functions cannot be critical";
1961 else if (is_reentrant_func (* node))
1962 message = "reentrant functions cannot be critical";
1964 else if (TREE_NAME_EQ (name, ATTR_NAKED))
1966 if (is_critical_func (* node))
1967 message = "critical functions cannot be naked";
1968 else if (is_reentrant_func (* node))
1969 message = "reentrant functions cannot be naked";
1972 if (message)
1974 warning (OPT_Wattributes, message, name);
1975 * no_add_attrs = true;
1978 return NULL_TREE;
1981 static tree
1982 msp430_section_attr (tree * node,
1983 tree name,
1984 tree args,
1985 int flags ATTRIBUTE_UNUSED,
1986 bool * no_add_attrs ATTRIBUTE_UNUSED)
1988 gcc_assert (DECL_P (* node));
1989 gcc_assert (args == NULL);
1991 const char * message = NULL;
1993 if (TREE_NAME_EQ (name, ATTR_UPPER))
1995 if (has_attr (ATTR_LOWER, * node))
1996 message = "already marked with 'lower' attribute";
1997 else if (has_attr (ATTR_EITHER, * node))
1998 message = "already marked with 'either' attribute";
1999 else if (! msp430x)
2000 message = "upper attribute needs a 430X cpu";
2002 else if (TREE_NAME_EQ (name, ATTR_LOWER))
2004 if (has_attr (ATTR_UPPER, * node))
2005 message = "already marked with 'upper' attribute";
2006 else if (has_attr (ATTR_EITHER, * node))
2007 message = "already marked with 'either' attribute";
2009 else
2011 gcc_assert (TREE_NAME_EQ (name, ATTR_EITHER));
2013 if (has_attr (ATTR_LOWER, * node))
2014 message = "already marked with 'lower' attribute";
2015 else if (has_attr (ATTR_UPPER, * node))
2016 message = "already marked with 'upper' attribute";
2019 if (message)
2021 warning (OPT_Wattributes, message, name);
2022 * no_add_attrs = true;
2025 return NULL_TREE;
2028 static tree
2029 msp430_data_attr (tree * node,
2030 tree name,
2031 tree args,
2032 int flags ATTRIBUTE_UNUSED,
2033 bool * no_add_attrs ATTRIBUTE_UNUSED)
2035 const char * message = NULL;
2037 gcc_assert (DECL_P (* node));
2038 gcc_assert (args == NULL);
2040 if (TREE_CODE (* node) != VAR_DECL)
2041 message = G_("%qE attribute only applies to variables");
2043 /* Check that it's possible for the variable to have a section. */
2044 if ((TREE_STATIC (* node) || DECL_EXTERNAL (* node) || in_lto_p)
2045 && DECL_SECTION_NAME (* node))
2046 message = G_("%qE attribute cannot be applied to variables with specific sections");
2048 if (!message && TREE_NAME_EQ (name, ATTR_PERSIST) && !TREE_STATIC (* node)
2049 && !TREE_PUBLIC (* node) && !DECL_EXTERNAL (* node))
2050 message = G_("%qE attribute has no effect on automatic variables");
2052 /* It's not clear if there is anything that can be set here to prevent the
2053 front end placing the variable before the back end can handle it, in a
2054 similar way to how DECL_COMMON is used below.
2055 So just place the variable in the .persistent section now. */
2056 if ((TREE_STATIC (* node) || DECL_EXTERNAL (* node) || in_lto_p)
2057 && TREE_NAME_EQ (name, ATTR_PERSIST))
2058 set_decl_section_name (* node, ".persistent");
2060 /* If this var is thought to be common, then change this. Common variables
2061 are assigned to sections before the backend has a chance to process them. */
2062 if (DECL_COMMON (* node))
2063 DECL_COMMON (* node) = 0;
2065 if (message)
2067 warning (OPT_Wattributes, message, name);
2068 * no_add_attrs = true;
2071 return NULL_TREE;
2075 #undef TARGET_ATTRIBUTE_TABLE
2076 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
2078 /* Table of MSP430-specific attributes. */
2079 const struct attribute_spec msp430_attribute_table[] =
2081 /* Name min_num_args type_req, handler
2082 max_num_args, fn_type_req exclude
2083 decl_req affects_type_identity. */
2084 { ATTR_INTR, 0, 1, true, false, false, false, msp430_attr, NULL },
2085 { ATTR_NAKED, 0, 0, true, false, false, false, msp430_attr, NULL },
2086 { ATTR_REENT, 0, 0, true, false, false, false, msp430_attr, NULL },
2087 { ATTR_CRIT, 0, 0, true, false, false, false, msp430_attr, NULL },
2088 { ATTR_WAKEUP, 0, 0, true, false, false, false, msp430_attr, NULL },
2090 { ATTR_LOWER, 0, 0, true, false, false, false, msp430_section_attr,
2091 NULL },
2092 { ATTR_UPPER, 0, 0, true, false, false, false, msp430_section_attr,
2093 NULL },
2094 { ATTR_EITHER, 0, 0, true, false, false, false, msp430_section_attr,
2095 NULL },
2097 { ATTR_NOINIT, 0, 0, true, false, false, false, msp430_data_attr,
2098 NULL },
2099 { ATTR_PERSIST, 0, 0, true, false, false, false, msp430_data_attr,
2100 NULL },
2102 { NULL, 0, 0, false, false, false, false, NULL, NULL }
2105 #undef TARGET_ASM_FUNCTION_PROLOGUE
2106 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
2108 static void
2109 msp430_start_function (FILE *outfile)
2111 int r, n;
2113 fprintf (outfile, "; start of function\n");
2115 if (DECL_ATTRIBUTES (current_function_decl) != NULL_TREE)
2117 fprintf (outfile, "; attributes: ");
2118 if (is_naked_func ())
2119 fprintf (outfile, "naked ");
2120 if (msp430_is_interrupt_func ())
2121 fprintf (outfile, "interrupt ");
2122 if (is_reentrant_func ())
2123 fprintf (outfile, "reentrant ");
2124 if (is_critical_func ())
2125 fprintf (outfile, "critical ");
2126 if (is_wakeup_func ())
2127 fprintf (outfile, "wakeup ");
2128 fprintf (outfile, "\n");
2131 fprintf (outfile, "; framesize_regs: %d\n", cfun->machine->framesize_regs);
2132 fprintf (outfile, "; framesize_locals: %d\n", cfun->machine->framesize_locals);
2133 fprintf (outfile, "; framesize_outgoing: %d\n", cfun->machine->framesize_outgoing);
2134 fprintf (outfile, "; framesize: %d\n", cfun->machine->framesize);
2135 fprintf (outfile, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM));
2136 fprintf (outfile, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM));
2138 n = 0;
2139 fprintf (outfile, "; saved regs:");
2140 for (r = 0; r < ARG_POINTER_REGNUM; r++)
2141 if (cfun->machine->need_to_save [r])
2143 fprintf (outfile, " %s", reg_names [r]);
2144 n = 1;
2146 if (n == 0)
2147 fprintf (outfile, "(none)");
2148 fprintf (outfile, "\n");
2151 /* Common code to change the stack pointer. */
2152 static void
2153 increment_stack (HOST_WIDE_INT amount)
2155 rtx inc;
2156 rtx sp = stack_pointer_rtx;
2158 if (amount == 0)
2159 return;
2161 if (amount < 0)
2163 inc = GEN_INT (- amount);
2164 if (TARGET_LARGE)
2165 F (emit_insn (gen_subpsi3 (sp, sp, inc)));
2166 else
2167 F (emit_insn (gen_subhi3 (sp, sp, inc)));
2169 else
2171 inc = GEN_INT (amount);
2172 if (TARGET_LARGE)
2173 emit_insn (gen_addpsi3 (sp, sp, inc));
2174 else
2175 emit_insn (gen_addhi3 (sp, sp, inc));
2179 void
2180 msp430_start_function (FILE *file, const char *name, tree decl)
2182 tree int_attr;
2184 int_attr = lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl));
2185 if (int_attr != NULL_TREE)
2187 tree intr_vector = TREE_VALUE (int_attr);
2189 if (intr_vector != NULL_TREE)
2191 char buf[101];
2193 /* Interrupt vector sections should be unique, but use of weak
2194 functions implies multiple definitions. */
2195 if (DECL_WEAK (decl))
2197 error ("argument to interrupt attribute is unsupported for weak functions");
2200 intr_vector = TREE_VALUE (intr_vector);
2202 /* The interrupt attribute has a vector value. Turn this into a
2203 section name, switch to that section and put the address of
2204 the current function into that vector slot. Note msp430_attr()
2205 has already verified the vector name for us. */
2206 if (TREE_CODE (intr_vector) == STRING_CST)
2207 sprintf (buf, "__interrupt_vector_%.80s",
2208 TREE_STRING_POINTER (intr_vector));
2209 else /* TREE_CODE (intr_vector) == INTEGER_CST */
2210 sprintf (buf, "__interrupt_vector_%u",
2211 (unsigned int) TREE_INT_CST_LOW (intr_vector));
2213 switch_to_section (get_section (buf, SECTION_CODE, decl));
2214 fputs ("\t.word\t", file);
2215 assemble_name (file, name);
2216 fputc ('\n', file);
2217 fputc ('\t', file);
2221 switch_to_section (function_section (decl));
2222 ASM_OUTPUT_TYPE_DIRECTIVE(file, name, "function");
2223 ASM_OUTPUT_FUNCTION_LABEL (file, name, decl);
2226 static const char * const lower_prefix = ".lower";
2227 static const char * const upper_prefix = ".upper";
2228 static const char * const either_prefix = ".either";
2230 /* Generate a prefix for a section name, based upon
2231 the region into which the object should be placed. */
2233 static const char *
2234 gen_prefix (tree decl)
2236 if (DECL_ONE_ONLY (decl))
2237 return NULL;
2239 /* If the user has specified a particular section then do not use any prefix. */
2240 if (has_attr ("section", decl))
2241 return NULL;
2243 /* If the function has been put in the .lowtext section (because it is an
2244 interrupt handler, and the large memory model is used), then do not add
2245 any prefixes. */
2246 if (has_section_name (".lowtext", decl))
2247 return NULL;
2249 /* If the object has __attribute__((lower)) then use the ".lower." prefix. */
2250 if (has_attr (ATTR_LOWER, decl))
2251 return lower_prefix;
2253 /* If we are compiling for the MSP430 then we do not support the upper region. */
2254 if (! msp430x)
2255 return NULL;
2257 if (has_attr (ATTR_UPPER, decl))
2258 return upper_prefix;
2260 if (has_attr (ATTR_EITHER, decl))
2261 return either_prefix;
2263 if (TREE_CODE (decl) == FUNCTION_DECL)
2265 if (msp430_code_region == MSP430_REGION_LOWER)
2266 return lower_prefix;
2268 if (msp430_code_region == MSP430_REGION_UPPER)
2269 return upper_prefix;
2271 if (msp430_code_region == MSP430_REGION_EITHER)
2272 return either_prefix;
2274 else
2276 if (msp430_data_region == MSP430_REGION_LOWER)
2277 return lower_prefix;
2279 if (msp430_data_region == MSP430_REGION_UPPER)
2280 return upper_prefix;
2282 if (msp430_data_region == MSP430_REGION_EITHER)
2283 return either_prefix;
2286 return NULL;
2289 static section * noinit_section;
2290 static section * persist_section;
2292 #undef TARGET_ASM_INIT_SECTIONS
2293 #define TARGET_ASM_INIT_SECTIONS msp430_init_sections
2295 static void
2296 msp430_init_sections (void)
2298 noinit_section = get_unnamed_section (0, output_section_asm_op, ".section .noinit,\"aw\"");
2299 persist_section = get_unnamed_section (0, output_section_asm_op, ".section .persistent,\"aw\"");
2302 #undef TARGET_ASM_SELECT_SECTION
2303 #define TARGET_ASM_SELECT_SECTION msp430_select_section
2305 static section *
2306 msp430_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
2308 gcc_assert (decl != NULL_TREE);
2310 if (TREE_CODE (decl) == STRING_CST
2311 || TREE_CODE (decl) == CONSTRUCTOR
2312 || TREE_CODE (decl) == INTEGER_CST
2313 || TREE_CODE (decl) == VECTOR_CST
2314 || TREE_CODE (decl) == COMPLEX_CST)
2315 return default_select_section (decl, reloc, align);
2317 /* In large mode we must make sure that interrupt handlers are put into
2318 low memory as the vector table only accepts 16-bit addresses. */
2319 if (TARGET_LARGE && TREE_CODE (decl) == FUNCTION_DECL && is_interrupt_func (decl))
2320 return get_section (".lowtext", SECTION_CODE | SECTION_WRITE , decl);
2322 const char * prefix = gen_prefix (decl);
2323 if (prefix == NULL)
2325 if (TREE_CODE (decl) == FUNCTION_DECL)
2326 return text_section;
2327 else if (has_attr (ATTR_NOINIT, decl))
2328 return noinit_section;
2329 else if (has_attr (ATTR_PERSIST, decl))
2330 return persist_section;
2331 else
2332 return default_select_section (decl, reloc, align);
2335 const char * sec;
2336 switch (categorize_decl_for_section (decl, reloc))
2338 case SECCAT_TEXT: sec = ".text"; break;
2339 case SECCAT_DATA: sec = ".data"; break;
2340 case SECCAT_BSS: sec = ".bss"; break;
2341 case SECCAT_RODATA: sec = ".rodata"; break;
2343 case SECCAT_RODATA_MERGE_STR:
2344 case SECCAT_RODATA_MERGE_STR_INIT:
2345 case SECCAT_RODATA_MERGE_CONST:
2346 case SECCAT_SRODATA:
2347 case SECCAT_DATA_REL:
2348 case SECCAT_DATA_REL_LOCAL:
2349 case SECCAT_DATA_REL_RO:
2350 case SECCAT_DATA_REL_RO_LOCAL:
2351 case SECCAT_SDATA:
2352 case SECCAT_SBSS:
2353 case SECCAT_TDATA:
2354 case SECCAT_TBSS:
2355 return default_select_section (decl, reloc, align);
2357 default:
2358 gcc_unreachable ();
2361 const char * dec_name = DECL_SECTION_NAME (decl);
2362 char * name = ACONCAT ((prefix, sec, dec_name, NULL));
2364 return get_named_section (decl, name, 0);
2367 #undef TARGET_ASM_FUNCTION_SECTION
2368 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
2370 static section *
2371 msp430_function_section (tree decl, enum node_frequency freq, bool startup, bool exit)
2373 const char * name;
2375 gcc_assert (DECL_SECTION_NAME (decl) != NULL);
2376 name = DECL_SECTION_NAME (decl);
2378 const char * prefix = gen_prefix (decl);
2379 if (prefix == NULL
2380 || strncmp (name, prefix, strlen (prefix)) == 0)
2381 return default_function_section (decl, freq, startup, exit);
2383 name = ACONCAT ((prefix, name, NULL));
2384 return get_named_section (decl, name, 0);
2387 #undef TARGET_SECTION_TYPE_FLAGS
2388 #define TARGET_SECTION_TYPE_FLAGS msp430_section_type_flags
2390 unsigned int
2391 msp430_section_type_flags (tree decl, const char * name, int reloc)
2393 if (strncmp (name, lower_prefix, strlen (lower_prefix)) == 0)
2394 name += strlen (lower_prefix);
2395 else if (strncmp (name, upper_prefix, strlen (upper_prefix)) == 0)
2396 name += strlen (upper_prefix);
2397 else if (strncmp (name, either_prefix, strlen (either_prefix)) == 0)
2398 name += strlen (either_prefix);
2399 else if (strcmp (name, ".noinit") == 0)
2400 return SECTION_WRITE | SECTION_BSS | SECTION_NOTYPE;
2401 else if (strcmp (name, ".persistent") == 0)
2402 return SECTION_WRITE | SECTION_NOTYPE;
2404 return default_section_type_flags (decl, name, reloc);
2407 #undef TARGET_ASM_UNIQUE_SECTION
2408 #define TARGET_ASM_UNIQUE_SECTION msp430_unique_section
2410 static void
2411 msp430_unique_section (tree decl, int reloc)
2413 gcc_assert (decl != NULL_TREE);
2415 /* In large mode we must make sure that interrupt handlers are put into
2416 low memory as the vector table only accepts 16-bit addresses. */
2417 if (TARGET_LARGE && TREE_CODE (decl) == FUNCTION_DECL && is_interrupt_func (decl))
2419 set_decl_section_name (decl, ".lowtext");
2420 return;
2423 default_unique_section (decl, reloc);
2425 const char * prefix;
2427 if ( TREE_CODE (decl) == STRING_CST
2428 || TREE_CODE (decl) == CONSTRUCTOR
2429 || TREE_CODE (decl) == INTEGER_CST
2430 || TREE_CODE (decl) == VECTOR_CST
2431 || TREE_CODE (decl) == COMPLEX_CST
2432 || (prefix = gen_prefix (decl)) == NULL
2434 return;
2436 const char * dec_name = DECL_SECTION_NAME (decl);
2437 char * name = ACONCAT ((prefix, dec_name, NULL));
2439 set_decl_section_name (decl, name);
2442 /* Emit a declaration of a common symbol.
2443 If a data region is in use then put the symbol into the
2444 equivalent .bss section instead. */
2446 void
2447 msp430_output_aligned_decl_common (FILE * stream,
2448 const tree decl,
2449 const char * name,
2450 unsigned HOST_WIDE_INT size,
2451 unsigned int align)
2453 if (msp430_data_region == MSP430_REGION_ANY)
2455 fprintf (stream, COMMON_ASM_OP);
2456 assemble_name (stream, name);
2457 fprintf (stream, "," HOST_WIDE_INT_PRINT_UNSIGNED",%u\n",
2458 size, align / BITS_PER_UNIT);
2460 else
2462 section * sec;
2464 if (decl)
2465 sec = msp430_select_section (decl, 0, align);
2466 else
2467 switch (msp430_data_region)
2469 case MSP430_REGION_UPPER: sec = get_named_section (NULL, ".upper.bss", 0); break;
2470 case MSP430_REGION_LOWER: sec = get_named_section (NULL, ".lower.bss", 0); break;
2471 case MSP430_REGION_EITHER: sec = get_named_section (NULL, ".either.bss", 0); break;
2472 default:
2473 gcc_unreachable ();
2475 gcc_assert (sec != NULL);
2477 switch_to_section (sec);
2478 ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
2479 targetm.asm_out.globalize_label (stream, name);
2480 ASM_WEAKEN_LABEL (stream, name);
2481 ASM_OUTPUT_LABEL (stream, name);
2482 ASM_OUTPUT_SKIP (stream, size ? size : 1);
2486 bool
2487 msp430_do_not_relax_short_jumps (void)
2489 /* When placing code into "either" low or high memory we do not want the linker
2490 to grow the size of sections, which it can do if it is encounters a branch to
2491 a label that is too far away. So we tell the cbranch patterns to avoid using
2492 short jumps when there is a chance that the instructions will end up in a low
2493 section. */
2494 return
2495 msp430_code_region == MSP430_REGION_EITHER
2496 || msp430_code_region == MSP430_REGION_LOWER
2497 || has_attr (ATTR_EITHER, current_function_decl)
2498 || has_attr (ATTR_LOWER, current_function_decl);
2501 enum msp430_builtin
2503 MSP430_BUILTIN_BIC_SR,
2504 MSP430_BUILTIN_BIS_SR,
2505 MSP430_BUILTIN_DELAY_CYCLES,
2506 MSP430_BUILTIN_max
2509 static GTY(()) tree msp430_builtins [(int) MSP430_BUILTIN_max];
2511 static void
2512 msp430_init_builtins (void)
2514 tree void_ftype_int = build_function_type_list (void_type_node, integer_type_node, NULL);
2515 tree void_ftype_longlong = build_function_type_list (void_type_node, long_long_integer_type_node, NULL);
2517 msp430_builtins[MSP430_BUILTIN_BIC_SR] =
2518 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int,
2519 MSP430_BUILTIN_BIC_SR, BUILT_IN_MD, NULL, NULL_TREE);
2521 msp430_builtins[MSP430_BUILTIN_BIS_SR] =
2522 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int,
2523 MSP430_BUILTIN_BIS_SR, BUILT_IN_MD, NULL, NULL_TREE);
2525 msp430_builtins[MSP430_BUILTIN_DELAY_CYCLES] =
2526 add_builtin_function ( "__delay_cycles", void_ftype_longlong,
2527 MSP430_BUILTIN_DELAY_CYCLES, BUILT_IN_MD, NULL, NULL_TREE);
2530 static tree
2531 msp430_builtin_decl (unsigned code, bool initialize ATTRIBUTE_UNUSED)
2533 switch (code)
2535 case MSP430_BUILTIN_BIC_SR:
2536 case MSP430_BUILTIN_BIS_SR:
2537 case MSP430_BUILTIN_DELAY_CYCLES:
2538 return msp430_builtins[code];
2539 default:
2540 return error_mark_node;
2544 /* These constants are really register reads, which are faster than
2545 regular constants. */
2546 static int
2547 cg_magic_constant (HOST_WIDE_INT c)
2549 switch (c)
2551 case 0xffff:
2552 case -1:
2553 case 0:
2554 case 1:
2555 case 2:
2556 case 4:
2557 case 8:
2558 return 1;
2559 default:
2560 return 0;
2564 static rtx
2565 msp430_expand_delay_cycles (rtx arg)
2567 HOST_WIDE_INT i, c, n;
2568 /* extra cycles for MSP430X instructions */
2569 #define CYCX(M,X) (msp430x ? (X) : (M))
2571 if (GET_CODE (arg) != CONST_INT)
2573 error ("__delay_cycles() only takes constant arguments");
2574 return NULL_RTX;
2577 c = INTVAL (arg);
2579 if (HOST_BITS_PER_WIDE_INT > 32)
2581 if (c < 0)
2583 error ("__delay_cycles only takes non-negative cycle counts");
2584 return NULL_RTX;
2588 emit_insn (gen_delay_cycles_start (arg));
2590 /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
2591 if (c > 3 * 0xffff + CYCX (7, 10))
2593 n = c;
2594 /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
2595 if (c >= 0x10000 * 7 + CYCX (14, 16))
2597 i = 0x10000;
2598 c -= CYCX (14, 16) + 7 * 0x10000;
2599 i += c / 4;
2600 c %= 4;
2601 if ((unsigned long long) i > 0xffffffffULL)
2603 error ("__delay_cycles is limited to 32-bit loop counts");
2604 return NULL_RTX;
2607 else
2609 i = (c - CYCX (14, 16)) / 7;
2610 c -= CYCX (14, 16) + i * 7;
2613 if (cg_magic_constant (i & 0xffff))
2614 c ++;
2615 if (cg_magic_constant ((i >> 16) & 0xffff))
2616 c ++;
2618 if (msp430x)
2619 emit_insn (gen_delay_cycles_32x (GEN_INT (i), GEN_INT (n - c)));
2620 else
2621 emit_insn (gen_delay_cycles_32 (GEN_INT (i), GEN_INT (n - c)));
2624 /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
2625 if (c > 12)
2627 n = c;
2628 i = (c - CYCX (7, 10)) / 3;
2629 c -= CYCX (7, 10) + i * 3;
2631 if (cg_magic_constant (i))
2632 c ++;
2634 if (msp430x)
2635 emit_insn (gen_delay_cycles_16x (GEN_INT (i), GEN_INT (n - c)));
2636 else
2637 emit_insn (gen_delay_cycles_16 (GEN_INT (i), GEN_INT (n - c)));
2640 while (c > 1)
2642 emit_insn (gen_delay_cycles_2 ());
2643 c -= 2;
2646 if (c)
2648 emit_insn (gen_delay_cycles_1 ());
2649 c -= 1;
2652 emit_insn (gen_delay_cycles_end (arg));
2654 return NULL_RTX;
2657 static rtx
2658 msp430_expand_builtin (tree exp,
2659 rtx target ATTRIBUTE_UNUSED,
2660 rtx subtarget ATTRIBUTE_UNUSED,
2661 machine_mode mode ATTRIBUTE_UNUSED,
2662 int ignore ATTRIBUTE_UNUSED)
2664 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
2665 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2666 rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
2668 if (fcode == MSP430_BUILTIN_DELAY_CYCLES)
2669 return msp430_expand_delay_cycles (arg1);
2671 if (! msp430_is_interrupt_func ())
2673 error ("MSP430 builtin functions only work inside interrupt handlers");
2674 return NULL_RTX;
2677 if (! REG_P (arg1) && ! CONSTANT_P (arg1))
2678 arg1 = force_reg (mode, arg1);
2680 switch (fcode)
2682 case MSP430_BUILTIN_BIC_SR: emit_insn (gen_bic_SR (arg1)); break;
2683 case MSP430_BUILTIN_BIS_SR: emit_insn (gen_bis_SR (arg1)); break;
2684 default:
2685 internal_error ("bad builtin code");
2686 break;
2688 return NULL_RTX;
2691 #undef TARGET_INIT_BUILTINS
2692 #define TARGET_INIT_BUILTINS msp430_init_builtins
2694 #undef TARGET_EXPAND_BUILTIN
2695 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
2697 #undef TARGET_BUILTIN_DECL
2698 #define TARGET_BUILTIN_DECL msp430_builtin_decl
2700 void
2701 msp430_expand_prologue (void)
2703 int i, j;
2704 int fs;
2705 /* Always use stack_pointer_rtx instead of calling
2706 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
2707 that there is a single rtx representing the stack pointer,
2708 namely stack_pointer_rtx, and uses == to recognize it. */
2709 rtx sp = stack_pointer_rtx;
2710 rtx p;
2712 if (is_naked_func ())
2714 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2715 examines the output of the gen_prologue() function. */
2716 emit_insn (gen_rtx_CLOBBER (VOIDmode, GEN_INT (0)));
2717 return;
2720 emit_insn (gen_prologue_start_marker ());
2722 if (is_critical_func ())
2724 emit_insn (gen_push_intr_state ());
2725 emit_insn (gen_disable_interrupts ());
2727 else if (is_reentrant_func ())
2728 emit_insn (gen_disable_interrupts ());
2730 if (!cfun->machine->computed)
2731 msp430_compute_frame_info ();
2733 if (flag_stack_usage_info)
2734 current_function_static_stack_size = cfun->machine->framesize;
2736 if (crtl->args.pretend_args_size)
2738 rtx note;
2740 gcc_assert (crtl->args.pretend_args_size == 2);
2742 p = emit_insn (gen_grow_and_swap ());
2744 /* Document the stack decrement... */
2745 note = F (gen_rtx_SET (stack_pointer_rtx,
2746 gen_rtx_MINUS (Pmode, stack_pointer_rtx, GEN_INT (2))));
2747 add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
2749 /* ...and the establishment of a new location for the return address. */
2750 note = F (gen_rtx_SET (gen_rtx_MEM (Pmode,
2751 gen_rtx_PLUS (Pmode,
2752 stack_pointer_rtx,
2753 GEN_INT (-2))),
2754 pc_rtx));
2755 add_reg_note (p, REG_CFA_OFFSET, note);
2756 F (p);
2759 for (i = 15; i >= 4; i--)
2760 if (cfun->machine->need_to_save [i])
2762 int seq, count;
2763 rtx note;
2765 for (seq = i - 1; seq >= 4 && cfun->machine->need_to_save[seq]; seq --)
2767 count = i - seq;
2769 if (msp430x)
2771 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
2772 p = F (emit_insn (gen_pushm (gen_rtx_REG (Pmode, i),
2773 GEN_INT (count))));
2775 note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1));
2777 XVECEXP (note, 0, 0)
2778 = F (gen_rtx_SET (stack_pointer_rtx,
2779 gen_rtx_PLUS (Pmode,
2780 stack_pointer_rtx,
2781 GEN_INT (count * (TARGET_LARGE ? -4 : -2)))));
2783 /* *sp-- = R[i-j] */
2784 /* sp+N R10
2786 sp R4 */
2787 for (j = 0; j < count; j ++)
2789 rtx addr;
2790 int ofs = (count - j - 1) * (TARGET_LARGE ? 4 : 2);
2792 if (ofs)
2793 addr = gen_rtx_PLUS (Pmode, sp, GEN_INT (ofs));
2794 else
2795 addr = stack_pointer_rtx;
2797 XVECEXP (note, 0, j + 1) =
2798 F (gen_rtx_SET (gen_rtx_MEM (Pmode, addr),
2799 gen_rtx_REG (Pmode, i - j)) );
2802 add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
2803 i -= count - 1;
2805 else
2806 F (emit_insn (gen_push (gen_rtx_REG (Pmode, i))));
2809 if (frame_pointer_needed)
2810 F (emit_move_insn (gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM), sp));
2812 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
2814 increment_stack (- fs);
2816 emit_insn (gen_prologue_end_marker ());
2819 void
2820 msp430_expand_epilogue (int is_eh)
2822 int i;
2823 int fs;
2824 int helper_n = 0;
2826 if (is_naked_func ())
2828 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2829 examines the output of the gen_epilogue() function. */
2830 emit_insn (gen_rtx_CLOBBER (VOIDmode, GEN_INT (0)));
2831 return;
2834 if (cfun->machine->need_to_save [10])
2836 /* Check for a helper function. */
2837 helper_n = 7; /* For when the loop below never sees a match. */
2838 for (i = 9; i >= 4; i--)
2839 if (!cfun->machine->need_to_save [i])
2841 helper_n = 10 - i;
2842 for (; i >= 4; i--)
2843 if (cfun->machine->need_to_save [i])
2845 helper_n = 0;
2846 break;
2848 break;
2852 emit_insn (gen_epilogue_start_marker ());
2854 if (cfun->decl && strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun->decl)), "main") == 0)
2855 emit_insn (gen_msp430_refsym_need_exit ());
2857 if (is_wakeup_func ())
2858 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
2859 status register current residing on the stack. When this function
2860 executes its RETI instruction the SR will be updated with this saved
2861 value, thus ensuring that the processor is woken up from any low power
2862 state in which it may be residing. */
2863 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
2865 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
2867 increment_stack (fs);
2869 if (is_eh)
2871 /* We need to add the right "SP" register save just after the
2872 regular ones, so that when we pop it off we're in the EH
2873 return frame, not this one. This overwrites our own return
2874 address, but we're not going to be returning anyway. */
2875 rtx r12 = gen_rtx_REG (Pmode, 12);
2876 rtx (*addPmode)(rtx, rtx, rtx) = TARGET_LARGE ? gen_addpsi3 : gen_addhi3;
2878 /* R12 will hold the new SP. */
2879 i = cfun->machine->framesize_regs;
2880 emit_move_insn (r12, stack_pointer_rtx);
2881 emit_insn (addPmode (r12, r12, EH_RETURN_STACKADJ_RTX));
2882 emit_insn (addPmode (r12, r12, GEN_INT (i)));
2883 emit_move_insn (gen_rtx_MEM (Pmode, plus_constant (Pmode, stack_pointer_rtx, i)), r12);
2886 for (i = 4; i <= 15; i++)
2887 if (cfun->machine->need_to_save [i])
2889 int seq, count;
2891 for (seq = i + 1; seq <= 15 && cfun->machine->need_to_save[seq]; seq ++)
2893 count = seq - i;
2895 if (msp430x)
2897 /* Note: With TARGET_LARGE we still use
2898 POPM as POPX.A is two bytes bigger. */
2899 emit_insn (gen_popm (stack_pointer_rtx, GEN_INT (seq - 1),
2900 GEN_INT (count)));
2901 i += count - 1;
2903 else if (i == 11 - helper_n
2904 && ! msp430_is_interrupt_func ()
2905 && ! is_reentrant_func ()
2906 && ! is_critical_func ()
2907 && crtl->args.pretend_args_size == 0
2908 /* Calling the helper takes as many bytes as the POP;RET sequence. */
2909 && helper_n > 1
2910 && !is_eh)
2912 emit_insn (gen_epilogue_helper (GEN_INT (helper_n)));
2913 return;
2915 else
2916 emit_insn (gen_pop (gen_rtx_REG (Pmode, i)));
2919 if (is_eh)
2921 /* Also pop SP, which puts us into the EH return frame. Except
2922 that you can't "pop" sp, you have to just load it off the
2923 stack. */
2924 emit_move_insn (stack_pointer_rtx, gen_rtx_MEM (Pmode, stack_pointer_rtx));
2927 if (crtl->args.pretend_args_size)
2928 emit_insn (gen_swap_and_shrink ());
2930 if (is_critical_func ())
2931 emit_insn (gen_pop_intr_state ());
2932 else if (is_reentrant_func ())
2933 emit_insn (gen_enable_interrupts ());
2935 emit_jump_insn (gen_msp_return ());
2938 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
2939 m32c_emit_eh_epilogue. */
2941 msp430_eh_return_stackadj_rtx (void)
2943 if (!cfun->machine->eh_stack_adjust)
2945 rtx sa;
2947 sa = gen_rtx_REG (Pmode, 15);
2948 cfun->machine->eh_stack_adjust = sa;
2950 return cfun->machine->eh_stack_adjust;
2953 /* This function is called before reload, to "fix" the stack in
2954 preparation for an EH return. */
2955 void
2956 msp430_expand_eh_return (rtx eh_handler)
2958 /* These are all Pmode */
2959 rtx ap, sa, ra, tmp;
2961 ap = arg_pointer_rtx;
2962 sa = msp430_eh_return_stackadj_rtx ();
2963 ra = eh_handler;
2965 tmp = ap;
2966 tmp = gen_rtx_PLUS (Pmode, ap, sa);
2967 tmp = plus_constant (Pmode, tmp, TARGET_LARGE ? -4 : -2);
2968 tmp = gen_rtx_MEM (Pmode, tmp);
2969 emit_move_insn (tmp, ra);
2972 #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
2973 #define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
2974 void
2975 msp430_init_dwarf_reg_sizes_extra (tree address)
2977 int i;
2978 rtx addr = expand_normal (address);
2979 rtx mem = gen_rtx_MEM (BLKmode, addr);
2981 /* This needs to match msp430_unwind_word_mode (above). */
2982 if (!msp430x)
2983 return;
2985 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2987 unsigned int dnum = DWARF_FRAME_REGNUM (i);
2988 unsigned int rnum = DWARF2_FRAME_REG_OUT (dnum, 1);
2990 if (rnum < DWARF_FRAME_REGISTERS)
2992 HOST_WIDE_INT offset = rnum * GET_MODE_SIZE (QImode);
2994 emit_move_insn (adjust_address (mem, QImode, offset),
2995 gen_int_mode (4, QImode));
3000 /* This is a list of MD patterns that implement fixed-count shifts. */
3001 static struct
3003 const char *name;
3004 int count;
3005 int need_430x;
3006 rtx (*genfunc)(rtx,rtx);
3008 const_shift_helpers[] =
3010 #define CSH(N,C,X,G) { "__mspabi_" N, C, X, gen_##G }
3012 CSH ("slli", 1, 1, slli_1),
3013 CSH ("slll", 1, 1, slll_1),
3014 CSH ("slll", 2, 1, slll_2),
3016 CSH ("srai", 1, 0, srai_1),
3017 CSH ("sral", 1, 0, sral_1),
3018 CSH ("sral", 2, 0, sral_2),
3020 CSH ("srll", 1, 0, srll_1),
3021 CSH ("srll", 2, 1, srll_2x),
3022 { 0, 0, 0, 0 }
3023 #undef CSH
3026 /* The MSP430 ABI defines a number of helper functions that should be
3027 used for, for example, 32-bit shifts. This function is called to
3028 emit such a function, using the table above to optimize some
3029 cases. */
3030 void
3031 msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variants)
3033 rtx c, f;
3034 char *helper_const = NULL;
3035 int arg2 = 13;
3036 int arg1sz = 1;
3037 machine_mode arg0mode = GET_MODE (operands[0]);
3038 machine_mode arg1mode = GET_MODE (operands[1]);
3039 machine_mode arg2mode = GET_MODE (operands[2]);
3040 int have_430x = msp430x ? 1 : 0;
3042 if (CONST_INT_P (operands[2]))
3044 int i;
3046 for (i=0; const_shift_helpers[i].name; i++)
3048 if (const_shift_helpers[i].need_430x <= have_430x
3049 && strcmp (helper_name, const_shift_helpers[i].name) == 0
3050 && INTVAL (operands[2]) == const_shift_helpers[i].count)
3052 emit_insn (const_shift_helpers[i].genfunc (operands[0], operands[1]));
3053 return;
3058 if (arg1mode == VOIDmode)
3059 arg1mode = arg0mode;
3060 if (arg2mode == VOIDmode)
3061 arg2mode = arg0mode;
3063 if (arg1mode == SImode)
3065 arg2 = 14;
3066 arg1sz = 2;
3069 if (const_variants
3070 && CONST_INT_P (operands[2])
3071 && INTVAL (operands[2]) >= 1
3072 && INTVAL (operands[2]) <= 15)
3074 /* Note that the INTVAL is limited in value and length by the conditional above. */
3075 int len = strlen (helper_name) + 4;
3076 helper_const = (char *) xmalloc (len);
3077 snprintf (helper_const, len, "%s_%d", helper_name, (int) INTVAL (operands[2]));
3080 emit_move_insn (gen_rtx_REG (arg1mode, 12),
3081 operands[1]);
3082 if (!helper_const)
3083 emit_move_insn (gen_rtx_REG (arg2mode, arg2),
3084 operands[2]);
3086 c = gen_call_value_internal (gen_rtx_REG (arg0mode, 12),
3087 gen_rtx_SYMBOL_REF (VOIDmode, helper_const ? helper_const : helper_name),
3088 GEN_INT (0));
3089 c = emit_call_insn (c);
3090 RTL_CONST_CALL_P (c) = 1;
3092 f = 0;
3093 use_regs (&f, 12, arg1sz);
3094 if (!helper_const)
3095 use_regs (&f, arg2, 1);
3096 add_function_usage_to (c, f);
3098 emit_move_insn (operands[0],
3099 gen_rtx_REG (arg0mode, 12));
3102 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
3103 void
3104 msp430_fixup_compare_operands (machine_mode my_mode, rtx * operands)
3106 /* constants we're looking for, not constants which are allowed. */
3107 int const_op_idx = 1;
3109 if (msp430_reversible_cmp_operator (operands[0], VOIDmode))
3110 const_op_idx = 2;
3112 if (GET_CODE (operands[const_op_idx]) != REG
3113 && GET_CODE (operands[const_op_idx]) != MEM)
3114 operands[const_op_idx] = copy_to_mode_reg (my_mode, operands[const_op_idx]);
3117 /* Simplify_gen_subreg() doesn't handle memory references the way we
3118 need it to below, so we use this function for when we must get a
3119 valid subreg in a "natural" state. */
3121 msp430_subreg (machine_mode mode, rtx r, machine_mode omode, int byte)
3123 rtx rv;
3125 if (GET_CODE (r) == SUBREG
3126 && SUBREG_BYTE (r) == 0)
3128 rtx ireg = SUBREG_REG (r);
3129 machine_mode imode = GET_MODE (ireg);
3131 /* special case for (HI (SI (PSI ...), 0)) */
3132 if (imode == PSImode
3133 && mode == HImode
3134 && byte == 0)
3135 rv = gen_rtx_SUBREG (mode, ireg, byte);
3136 else
3137 rv = simplify_gen_subreg (mode, ireg, imode, byte);
3139 else if (GET_CODE (r) == MEM)
3140 rv = adjust_address (r, mode, byte);
3141 else if (GET_CODE (r) == SYMBOL_REF
3142 && (byte == 0 || byte == 2)
3143 && mode == HImode)
3145 rv = gen_rtx_ZERO_EXTRACT (HImode, r, GEN_INT (16), GEN_INT (8*byte));
3146 rv = gen_rtx_CONST (HImode, r);
3148 else
3149 rv = simplify_gen_subreg (mode, r, omode, byte);
3151 if (!rv)
3152 gcc_unreachable ();
3154 return rv;
3157 /* Called by movsi_x to generate the HImode operands. */
3158 void
3159 msp430_split_movsi (rtx *operands)
3161 rtx op00, op02, op10, op12;
3163 op00 = msp430_subreg (HImode, operands[0], SImode, 0);
3164 op02 = msp430_subreg (HImode, operands[0], SImode, 2);
3166 if (GET_CODE (operands[1]) == CONST
3167 || GET_CODE (operands[1]) == SYMBOL_REF)
3169 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
3170 op10 = gen_rtx_CONST (HImode, op10);
3171 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
3172 op12 = gen_rtx_CONST (HImode, op12);
3174 else
3176 op10 = msp430_subreg (HImode, operands[1], SImode, 0);
3177 op12 = msp430_subreg (HImode, operands[1], SImode, 2);
3180 if (rtx_equal_p (operands[0], operands[1]))
3182 operands[2] = op02;
3183 operands[4] = op12;
3184 operands[3] = op00;
3185 operands[5] = op10;
3187 else if (rtx_equal_p (op00, op12)
3188 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
3189 || (REG_P (op00) && reg_mentioned_p (op00, op10))
3190 /* Or storing (rN) into mem (rN). */
3191 || (REG_P (op10) && reg_mentioned_p (op10, op00))
3194 operands[2] = op02;
3195 operands[4] = op12;
3196 operands[3] = op00;
3197 operands[5] = op10;
3199 else
3201 operands[2] = op00;
3202 operands[4] = op10;
3203 operands[3] = op02;
3204 operands[5] = op12;
3209 /* The MSPABI specifies the names of various helper functions, many of
3210 which are compatible with GCC's helpers. This table maps the GCC
3211 name to the MSPABI name. */
3212 static const struct
3214 char const * const gcc_name;
3215 char const * const ti_name;
3217 helper_function_name_mappings [] =
3219 /* Floating point to/from integer conversions. */
3220 { "__truncdfsf2", "__mspabi_cvtdf" },
3221 { "__extendsfdf2", "__mspabi_cvtfd" },
3222 { "__fixdfhi", "__mspabi_fixdi" },
3223 { "__fixdfsi", "__mspabi_fixdli" },
3224 { "__fixdfdi", "__mspabi_fixdlli" },
3225 { "__fixunsdfhi", "__mspabi_fixdu" },
3226 { "__fixunsdfsi", "__mspabi_fixdul" },
3227 { "__fixunsdfdi", "__mspabi_fixdull" },
3228 { "__fixsfhi", "__mspabi_fixfi" },
3229 { "__fixsfsi", "__mspabi_fixfli" },
3230 { "__fixsfdi", "__mspabi_fixflli" },
3231 { "__fixunsfhi", "__mspabi_fixfu" },
3232 { "__fixunsfsi", "__mspabi_fixful" },
3233 { "__fixunsfdi", "__mspabi_fixfull" },
3234 { "__floathisf", "__mspabi_fltif" },
3235 { "__floatsisf", "__mspabi_fltlif" },
3236 { "__floatdisf", "__mspabi_fltllif" },
3237 { "__floathidf", "__mspabi_fltid" },
3238 { "__floatsidf", "__mspabi_fltlid" },
3239 { "__floatdidf", "__mspabi_fltllid" },
3240 { "__floatunhisf", "__mspabi_fltuf" },
3241 { "__floatunsisf", "__mspabi_fltulf" },
3242 { "__floatundisf", "__mspabi_fltullf" },
3243 { "__floatunhidf", "__mspabi_fltud" },
3244 { "__floatunsidf", "__mspabi_fltuld" },
3245 { "__floatundidf", "__mspabi_fltulld" },
3247 /* Floating point comparisons. */
3248 /* GCC uses individual functions for each comparison, TI uses one
3249 compare <=> function. */
3251 /* Floating point arithmatic */
3252 { "__adddf3", "__mspabi_addd" },
3253 { "__addsf3", "__mspabi_addf" },
3254 { "__divdf3", "__mspabi_divd" },
3255 { "__divsf3", "__mspabi_divf" },
3256 { "__muldf3", "__mspabi_mpyd" },
3257 { "__mulsf3", "__mspabi_mpyf" },
3258 { "__subdf3", "__mspabi_subd" },
3259 { "__subsf3", "__mspabi_subf" },
3260 /* GCC does not use helper functions for negation */
3262 /* Integer multiply, divide, remainder. */
3263 { "__mulhi3", "__mspabi_mpyi" },
3264 { "__mulsi3", "__mspabi_mpyl" },
3265 { "__muldi3", "__mspabi_mpyll" },
3266 #if 0
3267 /* Clarify signed vs unsigned first. */
3268 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
3269 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
3270 #endif
3272 { "__divhi3", "__mspabi_divi" },
3273 { "__divsi3", "__mspabi_divli" },
3274 { "__divdi3", "__mspabi_divlli" },
3275 { "__udivhi3", "__mspabi_divu" },
3276 { "__udivsi3", "__mspabi_divul" },
3277 { "__udivdi3", "__mspabi_divull" },
3278 { "__modhi3", "__mspabi_remi" },
3279 { "__modsi3", "__mspabi_remli" },
3280 { "__moddi3", "__mspabi_remlli" },
3281 { "__umodhi3", "__mspabi_remu" },
3282 { "__umodsi3", "__mspabi_remul" },
3283 { "__umoddi3", "__mspabi_remull" },
3285 /* Bitwise operations. */
3286 /* Rotation - no rotation support yet. */
3287 /* Logical left shift - gcc already does these itself. */
3288 /* Arithmetic left shift - gcc already does these itself. */
3289 /* Arithmetic right shift - gcc already does these itself. */
3291 { NULL, NULL }
3294 /* Returns true if the current MCU supports an F5xxx series
3295 hardware multiper. */
3297 bool
3298 msp430_use_f5_series_hwmult (void)
3300 static const char * cached_match = NULL;
3301 static bool cached_result;
3303 if (msp430_hwmult_type == MSP430_HWMULT_F5SERIES)
3304 return true;
3306 if (target_mcu == NULL || msp430_hwmult_type != MSP430_HWMULT_AUTO)
3307 return false;
3309 if (target_mcu == cached_match)
3310 return cached_result;
3312 cached_match = target_mcu;
3314 if (strncasecmp (target_mcu, "msp430f5", 8) == 0)
3315 return cached_result = true;
3316 if (strncasecmp (target_mcu, "msp430fr5", 9) == 0)
3317 return cached_result = true;
3318 if (strncasecmp (target_mcu, "msp430f6", 8) == 0)
3319 return cached_result = true;
3321 int i;
3323 /* FIXME: This array is alpha sorted - we could use a binary search. */
3324 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
3325 if (strcasecmp (target_mcu, msp430_mcu_data[i].name) == 0)
3326 return cached_result = msp430_mcu_data[i].hwmpy == 8;
3328 return cached_result = false;
3331 /* Returns true if the current MCU has a second generation
3332 32-bit hardware multiplier. */
3334 static bool
3335 use_32bit_hwmult (void)
3337 static const char * cached_match = NULL;
3338 static bool cached_result;
3339 int i;
3341 if (msp430_hwmult_type == MSP430_HWMULT_LARGE)
3342 return true;
3344 if (target_mcu == NULL || msp430_hwmult_type != MSP430_HWMULT_AUTO)
3345 return false;
3347 if (target_mcu == cached_match)
3348 return cached_result;
3350 cached_match = target_mcu;
3352 /* FIXME: This array is alpha sorted - we could use a binary search. */
3353 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
3354 if (strcasecmp (target_mcu, msp430_mcu_data[i].name) == 0)
3355 return cached_result = msp430_mcu_data[i].hwmpy == 4;
3357 return cached_result = false;
3360 /* Returns true if the current MCU does not have a
3361 hardware multiplier of any kind. */
3363 static bool
3364 msp430_no_hwmult (void)
3366 static const char * cached_match = NULL;
3367 static bool cached_result;
3368 int i;
3370 if (msp430_hwmult_type == MSP430_HWMULT_NONE)
3371 return true;
3373 if (msp430_hwmult_type != MSP430_HWMULT_AUTO)
3374 return false;
3376 if (target_mcu == NULL)
3377 return true;
3379 if (target_mcu == cached_match)
3380 return cached_result;
3382 cached_match = target_mcu;
3384 /* FIXME: This array is alpha sorted - we could use a binary search. */
3385 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
3386 if (strcasecmp (target_mcu, msp430_mcu_data[i].name) == 0)
3387 return cached_result = msp430_mcu_data[i].hwmpy == 0;
3389 /* If we do not recognise the MCU name, we assume that it does not support
3390 any kind of hardware multiply - this is the safest assumption to make. */
3391 return cached_result = true;
3394 /* This function does the same as the default, but it will replace GCC
3395 function names with the MSPABI-specified ones. */
3397 void
3398 msp430_output_labelref (FILE *file, const char *name)
3400 int i;
3402 for (i = 0; helper_function_name_mappings [i].gcc_name; i++)
3403 if (strcmp (helper_function_name_mappings [i].gcc_name, name) == 0)
3405 name = helper_function_name_mappings [i].ti_name;
3406 break;
3409 /* If we have been given a specific MCU name then we may be
3410 able to make use of its hardware multiply capabilities. */
3411 if (msp430_hwmult_type != MSP430_HWMULT_NONE)
3413 if (strcmp ("__mspabi_mpyi", name) == 0)
3415 if (msp430_use_f5_series_hwmult ())
3416 name = "__mulhi2_f5";
3417 else if (! msp430_no_hwmult ())
3418 name = "__mulhi2";
3420 else if (strcmp ("__mspabi_mpyl", name) == 0)
3422 if (msp430_use_f5_series_hwmult ())
3423 name = "__mulsi2_f5";
3424 else if (use_32bit_hwmult ())
3425 name = "__mulsi2_hw32";
3426 else if (! msp430_no_hwmult ())
3427 name = "__mulsi2";
3431 if (user_label_prefix[0] != 0)
3432 fputs (user_label_prefix, file);
3434 fputs (name, file);
3437 /* Common code for msp430_print_operand... */
3439 static void
3440 msp430_print_operand_raw (FILE * file, rtx op)
3442 HOST_WIDE_INT i;
3444 switch (GET_CODE (op))
3446 case REG:
3447 fprintf (file, "%s", reg_names [REGNO (op)]);
3448 break;
3450 case CONST_INT:
3451 i = INTVAL (op);
3452 if (TARGET_ASM_HEX)
3453 fprintf (file, "%#" HOST_WIDE_INT_PRINT "x", i);
3454 else
3455 fprintf (file, "%" HOST_WIDE_INT_PRINT "d", i);
3456 break;
3458 case CONST:
3459 case PLUS:
3460 case MINUS:
3461 case SYMBOL_REF:
3462 case LABEL_REF:
3463 output_addr_const (file, op);
3464 break;
3466 default:
3467 print_rtl (file, op);
3468 break;
3472 #undef TARGET_ASM_ALIGNED_PSI_OP
3473 #define TARGET_ASM_ALIGNED_PSI_OP "\t.long\t"
3474 #undef TARGET_ASM_UNALIGNED_PSI_OP
3475 #define TARGET_ASM_UNALIGNED_PSI_OP TARGET_ASM_ALIGNED_PSI_OP
3477 #undef TARGET_PRINT_OPERAND_ADDRESS
3478 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
3480 /* Output to stdio stream FILE the assembler syntax for an
3481 instruction operand that is a memory reference whose address
3482 is ADDR. */
3484 static void
3485 msp430_print_operand_addr (FILE * file, machine_mode /*mode*/, rtx addr)
3487 switch (GET_CODE (addr))
3489 case PLUS:
3490 msp430_print_operand_raw (file, XEXP (addr, 1));
3491 gcc_assert (REG_P (XEXP (addr, 0)));
3492 fprintf (file, "(%s)", reg_names [REGNO (XEXP (addr, 0))]);
3493 return;
3495 case REG:
3496 fprintf (file, "@");
3497 break;
3499 case CONST:
3500 case CONST_INT:
3501 case SYMBOL_REF:
3502 case LABEL_REF:
3503 fprintf (file, "&");
3504 break;
3506 default:
3507 break;
3510 msp430_print_operand_raw (file, addr);
3513 #undef TARGET_PRINT_OPERAND
3514 #define TARGET_PRINT_OPERAND msp430_print_operand
3516 /* A low 16-bits of int/lower of register pair
3517 B high 16-bits of int/higher of register pair
3518 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
3519 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
3520 H like %B (for backwards compatibility)
3521 I inverse of value
3522 J an integer without a # prefix
3523 L like %A (for backwards compatibility)
3524 O offset of the top of the stack
3525 Q like X but generates an A postfix
3526 R inverse of condition code, unsigned.
3527 X X instruction postfix in large mode
3528 Y value - 4
3529 Z value - 1
3530 b .B or .W or .A, depending upon the mode
3531 p bit position
3532 r inverse of condition code
3533 x like X but only for pointers. */
3535 static void
3536 msp430_print_operand (FILE * file, rtx op, int letter)
3538 rtx addr;
3540 /* We can't use c, n, a, or l. */
3541 switch (letter)
3543 case 'Z':
3544 gcc_assert (CONST_INT_P (op));
3545 /* Print the constant value, less one. */
3546 fprintf (file, "#%ld", INTVAL (op) - 1);
3547 return;
3548 case 'Y':
3549 gcc_assert (CONST_INT_P (op));
3550 /* Print the constant value, less four. */
3551 fprintf (file, "#%ld", INTVAL (op) - 4);
3552 return;
3553 case 'I':
3554 if (GET_CODE (op) == CONST_INT)
3556 /* Inverse of constants */
3557 int i = INTVAL (op);
3558 fprintf (file, "%d", ~i);
3559 return;
3561 op = XEXP (op, 0);
3562 break;
3563 case 'r': /* Conditional jump where the condition is reversed. */
3564 switch (GET_CODE (op))
3566 case EQ: fprintf (file, "NE"); break;
3567 case NE: fprintf (file, "EQ"); break;
3568 case GEU: fprintf (file, "LO"); break;
3569 case LTU: fprintf (file, "HS"); break;
3570 case GE: fprintf (file, "L"); break;
3571 case LT: fprintf (file, "GE"); break;
3572 /* Assume these have reversed operands. */
3573 case GTU: fprintf (file, "HS"); break;
3574 case LEU: fprintf (file, "LO"); break;
3575 case GT: fprintf (file, "GE"); break;
3576 case LE: fprintf (file, "L"); break;
3577 default:
3578 msp430_print_operand_raw (file, op);
3579 break;
3581 return;
3582 case 'R': /* Conditional jump where the operands are reversed. */
3583 switch (GET_CODE (op))
3585 case GTU: fprintf (file, "LO"); break;
3586 case LEU: fprintf (file, "HS"); break;
3587 case GT: fprintf (file, "L"); break;
3588 case LE: fprintf (file, "GE"); break;
3589 default:
3590 msp430_print_operand_raw (file, op);
3591 break;
3593 return;
3594 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
3595 gcc_assert (CONST_INT_P (op));
3596 fprintf (file, "#%d", 1 << INTVAL (op));
3597 return;
3598 case 'b':
3599 switch (GET_MODE (op))
3601 case E_QImode: fprintf (file, ".B"); return;
3602 case E_HImode: fprintf (file, ".W"); return;
3603 case E_PSImode: fprintf (file, ".A"); return;
3604 case E_SImode: fprintf (file, ".A"); return;
3605 default:
3606 return;
3608 case 'A':
3609 case 'L': /* Low half. */
3610 switch (GET_CODE (op))
3612 case MEM:
3613 op = adjust_address (op, Pmode, 0);
3614 break;
3615 case REG:
3616 break;
3617 case CONST_INT:
3618 op = GEN_INT (INTVAL (op) & 0xffff);
3619 letter = 0;
3620 break;
3621 default:
3622 /* If you get here, figure out a test case :-) */
3623 gcc_unreachable ();
3625 break;
3626 case 'B':
3627 case 'H': /* high half */
3628 switch (GET_CODE (op))
3630 case MEM:
3631 op = adjust_address (op, Pmode, 2);
3632 break;
3633 case REG:
3634 op = gen_rtx_REG (Pmode, REGNO (op) + 1);
3635 break;
3636 case CONST_INT:
3637 op = GEN_INT (INTVAL (op) >> 16);
3638 letter = 0;
3639 break;
3640 default:
3641 /* If you get here, figure out a test case :-) */
3642 gcc_unreachable ();
3644 break;
3645 case 'C':
3646 switch (GET_CODE (op))
3648 case MEM:
3649 op = adjust_address (op, Pmode, 3);
3650 break;
3651 case REG:
3652 op = gen_rtx_REG (Pmode, REGNO (op) + 2);
3653 break;
3654 case CONST_INT:
3655 op = GEN_INT ((long long) INTVAL (op) >> 32);
3656 letter = 0;
3657 break;
3658 default:
3659 /* If you get here, figure out a test case :-) */
3660 gcc_unreachable ();
3662 break;
3663 case 'D':
3664 switch (GET_CODE (op))
3666 case MEM:
3667 op = adjust_address (op, Pmode, 4);
3668 break;
3669 case REG:
3670 op = gen_rtx_REG (Pmode, REGNO (op) + 3);
3671 break;
3672 case CONST_INT:
3673 op = GEN_INT ((long long) INTVAL (op) >> 48);
3674 letter = 0;
3675 break;
3676 default:
3677 /* If you get here, figure out a test case :-) */
3678 gcc_unreachable ();
3680 break;
3682 case 'X':
3683 /* This is used to turn, for example, an ADD opcode into an ADDX
3684 opcode when we're using 20-bit addresses. */
3685 if (TARGET_LARGE || GET_MODE (op) == PSImode)
3686 fprintf (file, "X");
3687 /* We don't care which operand we use, but we want 'X' in the MD
3688 file, so we do it this way. */
3689 return;
3691 case 'x':
3692 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
3693 if (GET_MODE (op) == PSImode)
3694 fprintf (file, "X");
3695 return;
3697 case 'Q':
3698 /* Likewise, for BR -> BRA. */
3699 if (TARGET_LARGE)
3700 fprintf (file, "A");
3701 return;
3703 case 'O':
3704 /* Computes the offset to the top of the stack for the current frame.
3705 This has to be done here rather than in, say, msp430_expand_builtin()
3706 because builtins are expanded before the frame layout is determined. */
3707 fprintf (file, "%d",
3708 msp430_initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM)
3709 - (TARGET_LARGE ? 4 : 2));
3710 return;
3712 case 'J':
3713 gcc_assert (GET_CODE (op) == CONST_INT);
3714 case 0:
3715 break;
3716 default:
3717 output_operand_lossage ("invalid operand prefix");
3718 return;
3721 switch (GET_CODE (op))
3723 case REG:
3724 msp430_print_operand_raw (file, op);
3725 break;
3727 case MEM:
3728 addr = XEXP (op, 0);
3729 msp430_print_operand_addr (file, GET_MODE (op), addr);
3730 break;
3732 case CONST:
3733 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTRACT)
3735 op = XEXP (op, 0);
3736 switch (INTVAL (XEXP (op, 2)))
3738 case 0:
3739 fprintf (file, "#lo (");
3740 msp430_print_operand_raw (file, XEXP (op, 0));
3741 fprintf (file, ")");
3742 break;
3744 case 16:
3745 fprintf (file, "#hi (");
3746 msp430_print_operand_raw (file, XEXP (op, 0));
3747 fprintf (file, ")");
3748 break;
3750 default:
3751 output_operand_lossage ("invalid zero extract");
3752 break;
3754 break;
3756 /* Fall through. */
3757 case CONST_INT:
3758 case SYMBOL_REF:
3759 case LABEL_REF:
3760 if (letter == 0)
3761 fprintf (file, "#");
3762 msp430_print_operand_raw (file, op);
3763 break;
3765 case EQ: fprintf (file, "EQ"); break;
3766 case NE: fprintf (file, "NE"); break;
3767 case GEU: fprintf (file, "HS"); break;
3768 case LTU: fprintf (file, "LO"); break;
3769 case GE: fprintf (file, "GE"); break;
3770 case LT: fprintf (file, "L"); break;
3772 default:
3773 print_rtl (file, op);
3774 break;
3779 /* Frame stuff. */
3782 msp430_return_addr_rtx (int count)
3784 int ra_size;
3785 if (count)
3786 return NULL_RTX;
3788 ra_size = TARGET_LARGE ? 4 : 2;
3789 if (crtl->args.pretend_args_size)
3790 ra_size += 2;
3792 return gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, arg_pointer_rtx, GEN_INT (- ra_size)));
3796 msp430_incoming_return_addr_rtx (void)
3798 return gen_rtx_MEM (Pmode, stack_pointer_rtx);
3801 /* Instruction generation stuff. */
3803 /* Generate a sequence of instructions to sign-extend an HI
3804 value into an SI value. Handles the tricky case where
3805 we are overwriting the destination. */
3807 const char *
3808 msp430x_extendhisi (rtx * operands)
3810 if (REGNO (operands[0]) == REGNO (operands[1]))
3811 /* Low word of dest == source word. */
3812 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
3814 if (! msp430x)
3815 /* Note: This sequence is approximately the same length as invoking a helper
3816 function to perform the sign-extension, as in:
3818 MOV.W %1, %L0
3819 MOV.W %1, r12
3820 CALL __mspabi_srai_15
3821 MOV.W r12, %H0
3823 but this version does not involve any function calls or using argument
3824 registers, so it reduces register pressure. */
3825 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
3827 if (REGNO (operands[0]) + 1 == REGNO (operands[1]))
3828 /* High word of dest == source word. */
3829 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
3831 /* No overlap between dest and source. */
3832 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
3835 /* Likewise for logical right shifts. */
3836 const char *
3837 msp430x_logical_shift_right (rtx amount)
3839 /* The MSP430X's logical right shift instruction - RRUM - does
3840 not use an extension word, so we cannot encode a repeat count.
3841 Try various alternatives to work around this. If the count
3842 is in a register we are stuck, hence the assert. */
3843 gcc_assert (CONST_INT_P (amount));
3845 if (INTVAL (amount) <= 0
3846 || INTVAL (amount) >= 16)
3847 return "# nop logical shift.";
3849 if (INTVAL (amount) > 0
3850 && INTVAL (amount) < 5)
3851 return "rrum.w\t%2, %0"; /* Two bytes. */
3853 if (INTVAL (amount) > 4
3854 && INTVAL (amount) < 9)
3855 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
3857 /* First we logically shift right by one. Now we know
3858 that the top bit is zero and we can use the arithmetic
3859 right shift instruction to perform the rest of the shift. */
3860 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
3863 /* Stop GCC from thinking that it can eliminate (SUBREG:PSI (SI)). */
3865 #undef TARGET_CAN_CHANGE_MODE_CLASS
3866 #define TARGET_CAN_CHANGE_MODE_CLASS msp430_can_change_mode_class
3868 static bool
3869 msp430_can_change_mode_class (machine_mode from, machine_mode to, reg_class_t)
3871 if ((to == PSImode && from == SImode)
3872 || (to == SImode && from == PSImode)
3873 || (to == DImode && from == PSImode)
3874 || (to == PSImode && from == DImode))
3875 return false;
3876 return true;
3879 #undef TARGET_HAVE_SPECULATION_SAFE_VALUE
3880 #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
3882 struct gcc_target targetm = TARGET_INITIALIZER;
3884 #include "gt-msp430.h"