re PR target/70713 (msp430 interrupt attribute prevents overriding weak symbols)
[official-gcc.git] / gcc / config / msp430 / msp430.c
blobc40d2da3e8a1ff66559dbf0ea172d202f94dc804
1 /* Subroutines used for code generation on TI MSP430 processors.
2 Copyright (C) 2012-2016 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 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "backend.h"
25 #include "target.h"
26 #include "rtl.h"
27 #include "tree.h"
28 #include "gimple-expr.h"
29 #include "df.h"
30 #include "tm_p.h"
31 #include "regs.h"
32 #include "emit-rtl.h"
33 #include "diagnostic-core.h"
34 #include "fold-const.h"
35 #include "stor-layout.h"
36 #include "calls.h"
37 #include "output.h"
38 #include "explow.h"
39 #include "expr.h"
40 #include "langhooks.h"
41 #include "builtins.h"
43 /* This file should be included last. */
44 #include "target-def.h"
47 static void msp430_compute_frame_info (void);
51 /* Run-time Target Specification. */
53 bool msp430x = true;
55 struct GTY(()) machine_function
57 /* If set, the rest of the fields have been computed. */
58 int computed;
59 /* Which registers need to be saved in the pro/epilogue. */
60 int need_to_save [FIRST_PSEUDO_REGISTER];
62 /* These fields describe the frame layout... */
63 /* arg pointer */
64 /* 2/4 bytes for saved PC */
65 int framesize_regs;
66 /* frame pointer */
67 int framesize_locals;
68 int framesize_outgoing;
69 /* stack pointer */
70 int framesize;
72 /* How much we adjust the stack when returning from an exception
73 handler. */
74 rtx eh_stack_adjust;
77 /* This is our init_machine_status, as set in
78 msp_option_override. */
79 static struct machine_function *
80 msp430_init_machine_status (void)
82 struct machine_function *m;
84 m = ggc_cleared_alloc<machine_function> ();
86 return m;
89 #undef TARGET_OPTION_OVERRIDE
90 #define TARGET_OPTION_OVERRIDE msp430_option_override
92 /* This is a copy of the same data structure found in gas/config/tc-msp430.c
93 Also another (sort-of) copy can be found in gcc/config/msp430/t-msp430
94 Keep these three structures in sync.
95 The data in this structure has been extracted from the devices.csv file
96 released by TI, updated as of March 2016. */
98 struct msp430_mcu_data
100 const char * name;
101 unsigned int revision; /* 0=> MSP430, 1=>MSP430X, 2=> MSP430Xv2. */
102 unsigned int hwmpy; /* 0=>none, 1=>16-bit, 2=>16-bit w/sign extend, 4=>32-bit, 8=> 32-bit (5xx). */
104 msp430_mcu_data [] =
106 { "cc430f5123",2,8 },
107 { "cc430f5125",2,8 },
108 { "cc430f5133",2,8 },
109 { "cc430f5135",2,8 },
110 { "cc430f5137",2,8 },
111 { "cc430f5143",2,8 },
112 { "cc430f5145",2,8 },
113 { "cc430f5147",2,8 },
114 { "cc430f6125",2,8 },
115 { "cc430f6126",2,8 },
116 { "cc430f6127",2,8 },
117 { "cc430f6135",2,8 },
118 { "cc430f6137",2,8 },
119 { "cc430f6143",2,8 },
120 { "cc430f6145",2,8 },
121 { "cc430f6147",2,8 },
122 { "msp430afe221",0,2 },
123 { "msp430afe222",0,2 },
124 { "msp430afe223",0,2 },
125 { "msp430afe231",0,2 },
126 { "msp430afe232",0,2 },
127 { "msp430afe233",0,2 },
128 { "msp430afe251",0,2 },
129 { "msp430afe252",0,2 },
130 { "msp430afe253",0,2 },
131 { "msp430bt5190",2,8 },
132 { "msp430c091",0,0 },
133 { "msp430c092",0,0 },
134 { "msp430c111",0,0 },
135 { "msp430c1111",0,0 },
136 { "msp430c112",0,0 },
137 { "msp430c1121",0,0 },
138 { "msp430c1331",0,0 },
139 { "msp430c1351",0,0 },
140 { "msp430c311s",0,0 },
141 { "msp430c312",0,0 },
142 { "msp430c313",0,0 },
143 { "msp430c314",0,0 },
144 { "msp430c315",0,0 },
145 { "msp430c323",0,0 },
146 { "msp430c325",0,0 },
147 { "msp430c336",0,1 },
148 { "msp430c337",0,1 },
149 { "msp430c412",0,0 },
150 { "msp430c413",0,0 },
151 { "msp430cg4616",1,1 },
152 { "msp430cg4617",1,1 },
153 { "msp430cg4618",1,1 },
154 { "msp430cg4619",1,1 },
155 { "msp430e112",0,0 },
156 { "msp430e313",0,0 },
157 { "msp430e315",0,0 },
158 { "msp430e325",0,0 },
159 { "msp430e337",0,1 },
160 { "msp430f110",0,0 },
161 { "msp430f1101",0,0 },
162 { "msp430f1101a",0,0 },
163 { "msp430f1111",0,0 },
164 { "msp430f1111a",0,0 },
165 { "msp430f112",0,0 },
166 { "msp430f1121",0,0 },
167 { "msp430f1121a",0,0 },
168 { "msp430f1122",0,0 },
169 { "msp430f1132",0,0 },
170 { "msp430f122",0,0 },
171 { "msp430f1222",0,0 },
172 { "msp430f123",0,0 },
173 { "msp430f1232",0,0 },
174 { "msp430f133",0,0 },
175 { "msp430f135",0,0 },
176 { "msp430f147",0,1 },
177 { "msp430f1471",0,1 },
178 { "msp430f148",0,1 },
179 { "msp430f1481",0,1 },
180 { "msp430f149",0,1 },
181 { "msp430f1491",0,1 },
182 { "msp430f155",0,0 },
183 { "msp430f156",0,0 },
184 { "msp430f157",0,0 },
185 { "msp430f1610",0,1 },
186 { "msp430f1611",0,1 },
187 { "msp430f1612",0,1 },
188 { "msp430f167",0,1 },
189 { "msp430f168",0,1 },
190 { "msp430f169",0,1 },
191 { "msp430f2001",0,0 },
192 { "msp430f2002",0,0 },
193 { "msp430f2003",0,0 },
194 { "msp430f2011",0,0 },
195 { "msp430f2012",0,0 },
196 { "msp430f2013",0,0 },
197 { "msp430f2101",0,0 },
198 { "msp430f2111",0,0 },
199 { "msp430f2112",0,0 },
200 { "msp430f2121",0,0 },
201 { "msp430f2122",0,0 },
202 { "msp430f2131",0,0 },
203 { "msp430f2132",0,0 },
204 { "msp430f2232",0,0 },
205 { "msp430f2234",0,0 },
206 { "msp430f2252",0,0 },
207 { "msp430f2254",0,0 },
208 { "msp430f2272",0,0 },
209 { "msp430f2274",0,0 },
210 { "msp430f233",0,2 },
211 { "msp430f2330",0,2 },
212 { "msp430f235",0,2 },
213 { "msp430f2350",0,2 },
214 { "msp430f2370",0,2 },
215 { "msp430f2410",0,2 },
216 { "msp430f2416",1,2 },
217 { "msp430f2417",1,2 },
218 { "msp430f2418",1,2 },
219 { "msp430f2419",1,2 },
220 { "msp430f247",0,2 },
221 { "msp430f2471",0,2 },
222 { "msp430f248",0,2 },
223 { "msp430f2481",0,2 },
224 { "msp430f249",0,2 },
225 { "msp430f2491",0,2 },
226 { "msp430f2616",1,2 },
227 { "msp430f2617",1,2 },
228 { "msp430f2618",1,2 },
229 { "msp430f2619",1,2 },
230 { "msp430f412",0,0 },
231 { "msp430f413",0,0 },
232 { "msp430f4132",0,0 },
233 { "msp430f415",0,0 },
234 { "msp430f4152",0,0 },
235 { "msp430f417",0,0 },
236 { "msp430f423",0,1 },
237 { "msp430f423a",0,1 },
238 { "msp430f425",0,1 },
239 { "msp430f4250",0,0 },
240 { "msp430f425a",0,1 },
241 { "msp430f4260",0,0 },
242 { "msp430f427",0,1 },
243 { "msp430f4270",0,0 },
244 { "msp430f427a",0,1 },
245 { "msp430f435",0,0 },
246 { "msp430f4351",0,0 },
247 { "msp430f436",0,0 },
248 { "msp430f4361",0,0 },
249 { "msp430f437",0,0 },
250 { "msp430f4371",0,0 },
251 { "msp430f438",0,0 },
252 { "msp430f439",0,0 },
253 { "msp430f447",0,1 },
254 { "msp430f448",0,1 },
255 { "msp430f4481",0,1 },
256 { "msp430f449",0,1 },
257 { "msp430f4491",0,1 },
258 { "msp430f4616",1,1 },
259 { "msp430f46161",1,1 },
260 { "msp430f4617",1,1 },
261 { "msp430f46171",1,1 },
262 { "msp430f4618",1,1 },
263 { "msp430f46181",1,1 },
264 { "msp430f4619",1,1 },
265 { "msp430f46191",1,1 },
266 { "msp430f47126",1,4 },
267 { "msp430f47127",1,4 },
268 { "msp430f47163",1,4 },
269 { "msp430f47166",1,4 },
270 { "msp430f47167",1,4 },
271 { "msp430f47173",1,4 },
272 { "msp430f47176",1,4 },
273 { "msp430f47177",1,4 },
274 { "msp430f47183",1,4 },
275 { "msp430f47186",1,4 },
276 { "msp430f47187",1,4 },
277 { "msp430f47193",1,4 },
278 { "msp430f47196",1,4 },
279 { "msp430f47197",1,4 },
280 { "msp430f477",0,0 },
281 { "msp430f478",0,0 },
282 { "msp430f4783",0,4 },
283 { "msp430f4784",0,4 },
284 { "msp430f479",0,0 },
285 { "msp430f4793",0,4 },
286 { "msp430f4794",0,4 },
287 { "msp430f5131",2,8 },
288 { "msp430f5132",2,8 },
289 { "msp430f5151",2,8 },
290 { "msp430f5152",2,8 },
291 { "msp430f5171",2,8 },
292 { "msp430f5172",2,8 },
293 { "msp430f5212",2,8 },
294 { "msp430f5213",2,8 },
295 { "msp430f5214",2,8 },
296 { "msp430f5217",2,8 },
297 { "msp430f5218",2,8 },
298 { "msp430f5219",2,8 },
299 { "msp430f5222",2,8 },
300 { "msp430f5223",2,8 },
301 { "msp430f5224",2,8 },
302 { "msp430f5227",2,8 },
303 { "msp430f5228",2,8 },
304 { "msp430f5229",2,8 },
305 { "msp430f5232",2,8 },
306 { "msp430f5234",2,8 },
307 { "msp430f5237",2,8 },
308 { "msp430f5239",2,8 },
309 { "msp430f5242",2,8 },
310 { "msp430f5244",2,8 },
311 { "msp430f5247",2,8 },
312 { "msp430f5249",2,8 },
313 { "msp430f5252",2,8 },
314 { "msp430f5253",2,8 },
315 { "msp430f5254",2,8 },
316 { "msp430f5255",2,8 },
317 { "msp430f5256",2,8 },
318 { "msp430f5257",2,8 },
319 { "msp430f5258",2,8 },
320 { "msp430f5259",2,8 },
321 { "msp430f5304",2,8 },
322 { "msp430f5308",2,8 },
323 { "msp430f5309",2,8 },
324 { "msp430f5310",2,8 },
325 { "msp430f5324",2,8 },
326 { "msp430f5325",2,8 },
327 { "msp430f5326",2,8 },
328 { "msp430f5327",2,8 },
329 { "msp430f5328",2,8 },
330 { "msp430f5329",2,8 },
331 { "msp430f5333",2,8 },
332 { "msp430f5335",2,8 },
333 { "msp430f5336",2,8 },
334 { "msp430f5338",2,8 },
335 { "msp430f5340",2,8 },
336 { "msp430f5341",2,8 },
337 { "msp430f5342",2,8 },
338 { "msp430f5358",2,8 },
339 { "msp430f5359",2,8 },
340 { "msp430f5418",2,8 },
341 { "msp430f5418a",2,8 },
342 { "msp430f5419",2,8 },
343 { "msp430f5419a",2,8 },
344 { "msp430f5435",2,8 },
345 { "msp430f5435a",2,8 },
346 { "msp430f5436",2,8 },
347 { "msp430f5436a",2,8 },
348 { "msp430f5437",2,8 },
349 { "msp430f5437a",2,8 },
350 { "msp430f5438",2,8 },
351 { "msp430f5438a",2,8 },
352 { "msp430f5500",2,8 },
353 { "msp430f5501",2,8 },
354 { "msp430f5502",2,8 },
355 { "msp430f5503",2,8 },
356 { "msp430f5504",2,8 },
357 { "msp430f5505",2,8 },
358 { "msp430f5506",2,8 },
359 { "msp430f5507",2,8 },
360 { "msp430f5508",2,8 },
361 { "msp430f5509",2,8 },
362 { "msp430f5510",2,8 },
363 { "msp430f5513",2,8 },
364 { "msp430f5514",2,8 },
365 { "msp430f5515",2,8 },
366 { "msp430f5517",2,8 },
367 { "msp430f5519",2,8 },
368 { "msp430f5521",2,8 },
369 { "msp430f5522",2,8 },
370 { "msp430f5524",2,8 },
371 { "msp430f5525",2,8 },
372 { "msp430f5526",2,8 },
373 { "msp430f5527",2,8 },
374 { "msp430f5528",2,8 },
375 { "msp430f5529",2,8 },
376 { "msp430f5630",2,8 },
377 { "msp430f5631",2,8 },
378 { "msp430f5632",2,8 },
379 { "msp430f5633",2,8 },
380 { "msp430f5634",2,8 },
381 { "msp430f5635",2,8 },
382 { "msp430f5636",2,8 },
383 { "msp430f5637",2,8 },
384 { "msp430f5638",2,8 },
385 { "msp430f5658",2,8 },
386 { "msp430f5659",2,8 },
387 { "msp430f5xx_6xxgeneric",2,8 },
388 { "msp430f6433",2,8 },
389 { "msp430f6435",2,8 },
390 { "msp430f6436",2,8 },
391 { "msp430f6438",2,8 },
392 { "msp430f6458",2,8 },
393 { "msp430f6459",2,8 },
394 { "msp430f6630",2,8 },
395 { "msp430f6631",2,8 },
396 { "msp430f6632",2,8 },
397 { "msp430f6633",2,8 },
398 { "msp430f6634",2,8 },
399 { "msp430f6635",2,8 },
400 { "msp430f6636",2,8 },
401 { "msp430f6637",2,8 },
402 { "msp430f6638",2,8 },
403 { "msp430f6658",2,8 },
404 { "msp430f6659",2,8 },
405 { "msp430f6720",2,8 },
406 { "msp430f6720a",2,8 },
407 { "msp430f6721",2,8 },
408 { "msp430f6721a",2,8 },
409 { "msp430f6723",2,8 },
410 { "msp430f6723a",2,8 },
411 { "msp430f6724",2,8 },
412 { "msp430f6724a",2,8 },
413 { "msp430f6725",2,8 },
414 { "msp430f6725a",2,8 },
415 { "msp430f6726",2,8 },
416 { "msp430f6726a",2,8 },
417 { "msp430f6730",2,8 },
418 { "msp430f6730a",2,8 },
419 { "msp430f6731",2,8 },
420 { "msp430f6731a",2,8 },
421 { "msp430f6733",2,8 },
422 { "msp430f6733a",2,8 },
423 { "msp430f6734",2,8 },
424 { "msp430f6734a",2,8 },
425 { "msp430f6735",2,8 },
426 { "msp430f6735a",2,8 },
427 { "msp430f6736",2,8 },
428 { "msp430f6736a",2,8 },
429 { "msp430f6745",2,8 },
430 { "msp430f67451",2,8 },
431 { "msp430f67451a",2,8 },
432 { "msp430f6745a",2,8 },
433 { "msp430f6746",2,8 },
434 { "msp430f67461",2,8 },
435 { "msp430f67461a",2,8 },
436 { "msp430f6746a",2,8 },
437 { "msp430f6747",2,8 },
438 { "msp430f67471",2,8 },
439 { "msp430f67471a",2,8 },
440 { "msp430f6747a",2,8 },
441 { "msp430f6748",2,8 },
442 { "msp430f67481",2,8 },
443 { "msp430f67481a",2,8 },
444 { "msp430f6748a",2,8 },
445 { "msp430f6749",2,8 },
446 { "msp430f67491",2,8 },
447 { "msp430f67491a",2,8 },
448 { "msp430f6749a",2,8 },
449 { "msp430f67621",2,8 },
450 { "msp430f67621a",2,8 },
451 { "msp430f67641",2,8 },
452 { "msp430f67641a",2,8 },
453 { "msp430f6765",2,8 },
454 { "msp430f67651",2,8 },
455 { "msp430f67651a",2,8 },
456 { "msp430f6765a",2,8 },
457 { "msp430f6766",2,8 },
458 { "msp430f67661",2,8 },
459 { "msp430f67661a",2,8 },
460 { "msp430f6766a",2,8 },
461 { "msp430f6767",2,8 },
462 { "msp430f67671",2,8 },
463 { "msp430f67671a",2,8 },
464 { "msp430f6767a",2,8 },
465 { "msp430f6768",2,8 },
466 { "msp430f67681",2,8 },
467 { "msp430f67681a",2,8 },
468 { "msp430f6768a",2,8 },
469 { "msp430f6769",2,8 },
470 { "msp430f67691",2,8 },
471 { "msp430f67691a",2,8 },
472 { "msp430f6769a",2,8 },
473 { "msp430f6775",2,8 },
474 { "msp430f67751",2,8 },
475 { "msp430f67751a",2,8 },
476 { "msp430f6775a",2,8 },
477 { "msp430f6776",2,8 },
478 { "msp430f67761",2,8 },
479 { "msp430f67761a",2,8 },
480 { "msp430f6776a",2,8 },
481 { "msp430f6777",2,8 },
482 { "msp430f67771",2,8 },
483 { "msp430f67771a",2,8 },
484 { "msp430f6777a",2,8 },
485 { "msp430f6778",2,8 },
486 { "msp430f67781",2,8 },
487 { "msp430f67781a",2,8 },
488 { "msp430f6778a",2,8 },
489 { "msp430f6779",2,8 },
490 { "msp430f67791",2,8 },
491 { "msp430f67791a",2,8 },
492 { "msp430f6779a",2,8 },
493 { "msp430fe423",0,0 },
494 { "msp430fe4232",0,0 },
495 { "msp430fe423a",0,0 },
496 { "msp430fe4242",0,0 },
497 { "msp430fe425",0,0 },
498 { "msp430fe4252",0,0 },
499 { "msp430fe425a",0,0 },
500 { "msp430fe427",0,0 },
501 { "msp430fe4272",0,0 },
502 { "msp430fe427a",0,0 },
503 { "msp430fg4250",0,0 },
504 { "msp430fg4260",0,0 },
505 { "msp430fg4270",0,0 },
506 { "msp430fg437",0,0 },
507 { "msp430fg438",0,0 },
508 { "msp430fg439",0,0 },
509 { "msp430fg4616",1,1 },
510 { "msp430fg4617",1,1 },
511 { "msp430fg4618",1,1 },
512 { "msp430fg4619",1,1 },
513 { "msp430fg477",0,0 },
514 { "msp430fg478",0,0 },
515 { "msp430fg479",0,0 },
516 { "msp430fg6425",2,8 },
517 { "msp430fg6426",2,8 },
518 { "msp430fg6625",2,8 },
519 { "msp430fg6626",2,8 },
520 { "msp430fr2032",2,0 },
521 { "msp430fr2033",2,0 },
522 { "msp430fr2310",2,0 },
523 { "msp430fr2311",2,0 },
524 { "msp430fr2433",2,8 },
525 { "msp430fr2532",2,8 },
526 { "msp430fr2533",2,8 },
527 { "msp430fr2632",2,8 },
528 { "msp430fr2633",2,8 },
529 { "msp430fr2xx_4xxgeneric",2,8 },
530 { "msp430fr4131",2,0 },
531 { "msp430fr4132",2,0 },
532 { "msp430fr4133",2,0 },
533 { "msp430fr5720",2,8 },
534 { "msp430fr5721",2,8 },
535 { "msp430fr5722",2,8 },
536 { "msp430fr5723",2,8 },
537 { "msp430fr5724",2,8 },
538 { "msp430fr5725",2,8 },
539 { "msp430fr5726",2,8 },
540 { "msp430fr5727",2,8 },
541 { "msp430fr5728",2,8 },
542 { "msp430fr5729",2,8 },
543 { "msp430fr5730",2,8 },
544 { "msp430fr5731",2,8 },
545 { "msp430fr5732",2,8 },
546 { "msp430fr5733",2,8 },
547 { "msp430fr5734",2,8 },
548 { "msp430fr5735",2,8 },
549 { "msp430fr5736",2,8 },
550 { "msp430fr5737",2,8 },
551 { "msp430fr5738",2,8 },
552 { "msp430fr5739",2,8 },
553 { "msp430fr57xxgeneric",2,8 },
554 { "msp430fr5847",2,8 },
555 { "msp430fr58471",2,8 },
556 { "msp430fr5848",2,8 },
557 { "msp430fr5849",2,8 },
558 { "msp430fr5857",2,8 },
559 { "msp430fr5858",2,8 },
560 { "msp430fr5859",2,8 },
561 { "msp430fr5867",2,8 },
562 { "msp430fr5862",2,8 },
563 { "msp430fr5864",2,8 },
564 { "msp430fr58671",2,8 },
565 { "msp430fr5868",2,8 },
566 { "msp430fr5869",2,8 },
567 { "msp430fr5870",2,8 },
568 { "msp430fr5872",2,8 },
569 { "msp430fr58721",2,8 },
570 { "msp430fr5887",2,8 },
571 { "msp430fr5888",2,8 },
572 { "msp430fr5889",2,8 },
573 { "msp430fr58891",2,8 },
574 { "msp430fr5892",2,8 },
575 { "msp430fr5894",2,8 },
576 { "msp430fr5922",2,8 },
577 { "msp430fr59221",2,8 },
578 { "msp430fr5947",2,8 },
579 { "msp430fr59471",2,8 },
580 { "msp430fr5948",2,8 },
581 { "msp430fr5949",2,8 },
582 { "msp430fr5957",2,8 },
583 { "msp430fr5958",2,8 },
584 { "msp430fr5959",2,8 },
585 { "msp430fr5962",2,8 },
586 { "msp430fr5964",2,8 },
587 { "msp430fr5967",2,8 },
588 { "msp430fr5968",2,8 },
589 { "msp430fr5969",2,8 },
590 { "msp430fr59691",2,8 },
591 { "msp430fr5970",2,8 },
592 { "msp430fr5972",2,8 },
593 { "msp430fr59721",2,8 },
594 { "msp430fr5986",2,8 },
595 { "msp430fr5987",2,8 },
596 { "msp430fr5988",2,8 },
597 { "msp430fr5989",2,8 },
598 { "msp430fr59891",2,8 },
599 { "msp430fr5992",2,8 },
600 { "msp430fr5994",2,8 },
601 { "msp430fr5xx_6xxgeneric",2,8 },
602 { "msp430fr6820",2,8 },
603 { "msp430fr6822",2,8 },
604 { "msp430fr68221",2,8 },
605 { "msp430fr6870",2,8 },
606 { "msp430fr6872",2,8 },
607 { "msp430fr68721",2,8 },
608 { "msp430fr6877",2,8 },
609 { "msp430fr6879",2,8 },
610 { "msp430fr68791",2,8 },
611 { "msp430fr6887",2,8 },
612 { "msp430fr6888",2,8 },
613 { "msp430fr6889",2,8 },
614 { "msp430fr68891",2,8 },
615 { "msp430fr6920",2,8 },
616 { "msp430fr6922",2,8 },
617 { "msp430fr69221",2,8 },
618 { "msp430fr6927",2,8 },
619 { "msp430fr69271",2,8 },
620 { "msp430fr6928",2,8 },
621 { "msp430fr6970",2,8 },
622 { "msp430fr6972",2,8 },
623 { "msp430fr69721",2,8 },
624 { "msp430fr6977",2,8 },
625 { "msp430fr6979",2,8 },
626 { "msp430fr69791",2,8 },
627 { "msp430fr6987",2,8 },
628 { "msp430fr6988",2,8 },
629 { "msp430fr6989",2,8 },
630 { "msp430fr69891",2,8 },
631 { "msp430fw423",0,0 },
632 { "msp430fw425",0,0 },
633 { "msp430fw427",0,0 },
634 { "msp430fw428",0,0 },
635 { "msp430fw429",0,0 },
636 { "msp430g2001",0,0 },
637 { "msp430g2101",0,0 },
638 { "msp430g2102",0,0 },
639 { "msp430g2111",0,0 },
640 { "msp430g2112",0,0 },
641 { "msp430g2113",0,0 },
642 { "msp430g2121",0,0 },
643 { "msp430g2131",0,0 },
644 { "msp430g2132",0,0 },
645 { "msp430g2152",0,0 },
646 { "msp430g2153",0,0 },
647 { "msp430g2201",0,0 },
648 { "msp430g2202",0,0 },
649 { "msp430g2203",0,0 },
650 { "msp430g2210",0,0 },
651 { "msp430g2211",0,0 },
652 { "msp430g2212",0,0 },
653 { "msp430g2213",0,0 },
654 { "msp430g2221",0,0 },
655 { "msp430g2230",0,0 },
656 { "msp430g2231",0,0 },
657 { "msp430g2232",0,0 },
658 { "msp430g2233",0,0 },
659 { "msp430g2252",0,0 },
660 { "msp430g2253",0,0 },
661 { "msp430g2302",0,0 },
662 { "msp430g2303",0,0 },
663 { "msp430g2312",0,0 },
664 { "msp430g2313",0,0 },
665 { "msp430g2332",0,0 },
666 { "msp430g2333",0,0 },
667 { "msp430g2352",0,0 },
668 { "msp430g2353",0,0 },
669 { "msp430g2402",0,0 },
670 { "msp430g2403",0,0 },
671 { "msp430g2412",0,0 },
672 { "msp430g2413",0,0 },
673 { "msp430g2432",0,0 },
674 { "msp430g2433",0,0 },
675 { "msp430g2444",0,0 },
676 { "msp430g2452",0,0 },
677 { "msp430g2453",0,0 },
678 { "msp430g2513",0,0 },
679 { "msp430g2533",0,0 },
680 { "msp430g2544",0,0 },
681 { "msp430g2553",0,0 },
682 { "msp430g2744",0,0 },
683 { "msp430g2755",0,0 },
684 { "msp430g2855",0,0 },
685 { "msp430g2955",0,0 },
686 { "msp430i2020",0,2 },
687 { "msp430i2021",0,2 },
688 { "msp430i2030",0,2 },
689 { "msp430i2031",0,2 },
690 { "msp430i2040",0,2 },
691 { "msp430i2041",0,2 },
692 { "msp430i2xxgeneric",0,2 },
693 { "msp430l092",0,0 },
694 { "msp430p112",0,0 },
695 { "msp430p313",0,0 },
696 { "msp430p315",0,0 },
697 { "msp430p315s",0,0 },
698 { "msp430p325",0,0 },
699 { "msp430p337",0,1 },
700 { "msp430sl5438a",2,8 },
701 { "msp430tch5e",0,0 },
702 { "msp430xgeneric",2,8 },
703 { "rf430f5144",2,8 },
704 { "rf430f5155",2,8 },
705 { "rf430f5175",2,8 },
706 { "rf430frl152h",0,0 },
707 { "rf430frl152h_rom",0,0 },
708 { "rf430frl153h",0,0 },
709 { "rf430frl153h_rom",0,0 },
710 { "rf430frl154h",0,0 },
711 { "rf430frl154h_rom",0,0 }
714 /* Generate a C preprocessor symbol based upon the MCU selected by the user.
715 If a specific MCU has not been selected then return a generic symbol instead. */
717 const char *
718 msp430_mcu_name (void)
720 if (target_mcu)
722 unsigned int i;
723 static char mcu_name [64];
725 snprintf (mcu_name, sizeof (mcu_name) - 1, "__%s__", target_mcu);
726 for (i = strlen (mcu_name); i--;)
727 mcu_name[i] = TOUPPER (mcu_name[i]);
728 return mcu_name;
731 return msp430x ? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
734 static const char *
735 hwmult_name (unsigned int val)
737 switch (val)
739 case 0: return "none";
740 case 1: return "16-bit";
741 case 2: return "16-bit";
742 case 4: return "32-bit";
743 case 8: return "32-bit (5xx)";
744 default: gcc_unreachable ();
748 static void
749 msp430_option_override (void)
751 init_machine_status = msp430_init_machine_status;
753 if (target_cpu)
755 /* gcc/common/config/msp430-common.c will have
756 already canonicalised the string in target_cpu. */
757 if (strcasecmp (target_cpu, "msp430x") == 0)
758 msp430x = true;
759 else /* target_cpu == "msp430" - already handled by the front end. */
760 msp430x = false;
763 if (target_mcu)
765 int i;
767 /* FIXME: If the array were alpha sorted, we could use a binary search. */
768 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
769 if (strcasecmp (msp430_mcu_data[i].name, target_mcu) == 0)
771 bool xisa = msp430_mcu_data[i].revision >= 1;
773 if (msp430_warn_mcu)
775 if (target_cpu&& msp430x != xisa)
776 warning (0, "MCU '%s' supports %s ISA but -mcpu option is set to %s",
777 target_mcu, xisa ? "430X" : "430", msp430x ? "430X" : "430");
779 if (msp430_mcu_data[i].hwmpy == 0
780 && msp430_hwmult_type != MSP430_HWMULT_AUTO
781 && msp430_hwmult_type != MSP430_HWMULT_NONE)
782 warning (0, "MCU '%s' does not have hardware multiply support, but -mhwmult is set to %s",
783 target_mcu,
784 msp430_hwmult_type == MSP430_HWMULT_SMALL ? "16-bit"
785 : msp430_hwmult_type == MSP430_HWMULT_LARGE ? "32-bit" : "f5series");
786 else if (msp430_hwmult_type == MSP430_HWMULT_SMALL
787 && msp430_mcu_data[i].hwmpy != 1
788 && msp430_mcu_data[i].hwmpy != 2 )
789 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to 16-bit",
790 target_mcu, hwmult_name (msp430_mcu_data[i].hwmpy));
791 else if (msp430_hwmult_type == MSP430_HWMULT_LARGE && msp430_mcu_data[i].hwmpy != 4)
792 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to 32-bit",
793 target_mcu, hwmult_name (msp430_mcu_data[i].hwmpy));
794 else if (msp430_hwmult_type == MSP430_HWMULT_F5SERIES && msp430_mcu_data[i].hwmpy != 8)
795 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to f5series",
796 target_mcu, hwmult_name (msp430_mcu_data[i].hwmpy));
799 msp430x = xisa;
800 break;
803 if (i < 0)
805 if (msp430_hwmult_type == MSP430_HWMULT_AUTO)
807 if (msp430_warn_mcu)
809 if (target_cpu == NULL)
810 warning (0,
811 "Unrecognised MCU name '%s', assuming that it is just a MSP430 with no hardware multiply.\nUse the -mcpu and -mhwmult options to set these explicitly.",
812 target_mcu);
813 else
814 warning (0,
815 "Unrecognised MCU name '%s', assuming that it has no hardware multiply.\nUse the -mhwmult option to set this explicitly.",
816 target_mcu);
819 msp430_hwmult_type = MSP430_HWMULT_NONE;
821 else if (target_cpu == NULL)
823 if (msp430_warn_mcu)
824 warning (0,
825 "Unrecognised MCU name '%s', assuming that it just supports the MSP430 ISA.\nUse the -mcpu option to set the ISA explicitly.",
826 target_mcu);
828 msp430x = false;
830 else if (msp430_warn_mcu)
831 warning (0,
832 "Unrecognised MCU name '%s'.", target_mcu);
836 /* The F5 series are all able to support the 430X ISA. */
837 if (target_cpu == NULL && target_mcu == NULL && msp430_hwmult_type == MSP430_HWMULT_F5SERIES)
838 msp430x = true;
840 if (TARGET_LARGE && !msp430x)
841 error ("-mlarge requires a 430X-compatible -mmcu=");
843 if (msp430_code_region == MSP430_REGION_UPPER && ! msp430x)
844 error ("-mcode-region=upper requires 430X-compatible cpu");
845 if (msp430_data_region == MSP430_REGION_UPPER && ! msp430x)
846 error ("-mdata-region=upper requires 430X-compatible cpu");
848 if (flag_exceptions || flag_non_call_exceptions
849 || flag_unwind_tables || flag_asynchronous_unwind_tables)
850 flag_omit_frame_pointer = false;
851 else
852 flag_omit_frame_pointer = true;
854 /* This is a hack to work around a problem with the newlib build
855 mechanism. Newlib always appends CFLAGS to the end of the GCC
856 command line and always sets -O2 in CFLAGS. Thus it is not
857 possible to build newlib with -Os enabled. Until now... */
858 if (TARGET_OPT_SPACE && optimize < 3)
859 optimize_size = 1;
862 #undef TARGET_SCALAR_MODE_SUPPORTED_P
863 #define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
865 static bool
866 msp430_scalar_mode_supported_p (machine_mode m)
868 if (m == PSImode && msp430x)
869 return true;
870 #if 0
871 if (m == TImode)
872 return true;
873 #endif
874 return default_scalar_mode_supported_p (m);
879 /* Storage Layout */
881 #undef TARGET_MS_BITFIELD_LAYOUT_P
882 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
884 bool
885 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED)
887 return false;
892 /* Register Usage */
894 /* Implements HARD_REGNO_NREGS. MSP430X registers can hold a single
895 PSImode value, but not an SImode value. */
897 msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED,
898 machine_mode mode)
900 if (mode == PSImode && msp430x)
901 return 1;
902 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
903 / UNITS_PER_WORD);
906 /* Implements HARD_REGNO_NREGS_HAS_PADDING. */
908 msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED,
909 machine_mode mode)
911 if (mode == PSImode && msp430x)
912 return 1;
913 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
914 / UNITS_PER_WORD);
917 /* Implements HARD_REGNO_NREGS_WITH_PADDING. */
919 msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED,
920 machine_mode mode)
922 if (mode == PSImode)
923 return 2;
924 return msp430_hard_regno_nregs (regno, mode);
927 /* Implements HARD_REGNO_MODE_OK. */
929 msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED,
930 machine_mode mode)
932 return regno <= (ARG_POINTER_REGNUM - msp430_hard_regno_nregs (regno, mode));
935 /* Implements MODES_TIEABLE_P. */
936 bool
937 msp430_modes_tieable_p (machine_mode mode1, machine_mode mode2)
939 if ((mode1 == PSImode || mode2 == SImode)
940 || (mode1 == SImode || mode2 == PSImode))
941 return false;
943 return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
944 || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
945 == (GET_MODE_CLASS (mode2) == MODE_FLOAT
946 || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
949 #undef TARGET_FRAME_POINTER_REQUIRED
950 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
952 static bool
953 msp430_frame_pointer_required (void)
955 return false;
958 #undef TARGET_CAN_ELIMINATE
959 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
961 static bool
962 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED,
963 const int to_reg ATTRIBUTE_UNUSED)
965 return true;
968 /* Implements INITIAL_ELIMINATION_OFFSET. */
970 msp430_initial_elimination_offset (int from, int to)
972 int rv = 0; /* As if arg to arg. */
974 msp430_compute_frame_info ();
976 switch (to)
978 case STACK_POINTER_REGNUM:
979 rv += cfun->machine->framesize_outgoing;
980 rv += cfun->machine->framesize_locals;
981 /* Fall through. */
982 case FRAME_POINTER_REGNUM:
983 rv += cfun->machine->framesize_regs;
984 /* Allow for the saved return address. */
985 rv += (TARGET_LARGE ? 4 : 2);
986 /* NB/ No need to allow for crtl->args.pretend_args_size.
987 GCC does that for us. */
988 break;
989 default:
990 gcc_unreachable ();
993 switch (from)
995 case FRAME_POINTER_REGNUM:
996 /* Allow for the fall through above. */
997 rv -= (TARGET_LARGE ? 4 : 2);
998 rv -= cfun->machine->framesize_regs;
999 case ARG_POINTER_REGNUM:
1000 break;
1001 default:
1002 gcc_unreachable ();
1005 return rv;
1008 /* Named Address Space support */
1011 /* Return the appropriate mode for a named address pointer. */
1012 #undef TARGET_ADDR_SPACE_POINTER_MODE
1013 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
1014 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
1015 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
1017 static machine_mode
1018 msp430_addr_space_pointer_mode (addr_space_t addrspace)
1020 switch (addrspace)
1022 default:
1023 case ADDR_SPACE_GENERIC:
1024 return Pmode;
1025 case ADDR_SPACE_NEAR:
1026 return HImode;
1027 case ADDR_SPACE_FAR:
1028 return PSImode;
1032 /* Function pointers are stored in unwind_word sized
1033 variables, so make sure that unwind_word is big enough. */
1034 #undef TARGET_UNWIND_WORD_MODE
1035 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
1037 static machine_mode
1038 msp430_unwind_word_mode (void)
1040 /* This needs to match msp430_init_dwarf_reg_sizes_extra (below). */
1041 return msp430x ? PSImode : HImode;
1044 /* Determine if one named address space is a subset of another. */
1045 #undef TARGET_ADDR_SPACE_SUBSET_P
1046 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
1047 static bool
1048 msp430_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
1050 if (subset == superset)
1051 return true;
1052 else
1053 return (subset != ADDR_SPACE_FAR && superset == ADDR_SPACE_FAR);
1056 #undef TARGET_ADDR_SPACE_CONVERT
1057 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
1058 /* Convert from one address space to another. */
1059 static rtx
1060 msp430_addr_space_convert (rtx op, tree from_type, tree to_type)
1062 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
1063 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
1064 rtx result;
1066 if (to_as != ADDR_SPACE_FAR && from_as == ADDR_SPACE_FAR)
1068 /* This is unpredictable, as we're truncating off usable address
1069 bits. */
1071 if (CONSTANT_P (op))
1072 return gen_rtx_CONST (HImode, op);
1074 result = gen_reg_rtx (HImode);
1075 emit_insn (gen_truncpsihi2 (result, op));
1076 return result;
1078 else if (to_as == ADDR_SPACE_FAR && from_as != ADDR_SPACE_FAR)
1080 /* This always works. */
1082 if (CONSTANT_P (op))
1083 return gen_rtx_CONST (PSImode, op);
1085 result = gen_reg_rtx (PSImode);
1086 emit_insn (gen_zero_extendhipsi2 (result, op));
1087 return result;
1089 else
1090 gcc_unreachable ();
1093 /* Stack Layout and Calling Conventions. */
1095 /* For each function, we list the gcc version and the TI version on
1096 each line, where we're converting the function names. */
1097 static char const * const special_convention_function_names [] =
1099 "__muldi3", "__mspabi_mpyll",
1100 "__udivdi3", "__mspabi_divull",
1101 "__umoddi3", "__mspabi_remull",
1102 "__divdi3", "__mspabi_divlli",
1103 "__moddi3", "__mspabi_remlli",
1104 "__mspabi_srall",
1105 "__mspabi_srlll",
1106 "__mspabi_sllll",
1107 "__adddf3", "__mspabi_addd",
1108 "__subdf3", "__mspabi_subd",
1109 "__muldf3", "__mspabi_mpyd",
1110 "__divdf3", "__mspabi_divd",
1111 "__mspabi_cmpd",
1112 NULL
1115 /* TRUE if the function passed is a "speical" function. Special
1116 functions pass two DImode parameters in registers. */
1117 static bool
1118 msp430_special_register_convention_p (const char *name)
1120 int i;
1122 for (i = 0; special_convention_function_names [i]; i++)
1123 if (! strcmp (name, special_convention_function_names [i]))
1124 return true;
1126 return false;
1129 #undef TARGET_FUNCTION_VALUE_REGNO_P
1130 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
1132 bool
1133 msp430_function_value_regno_p (unsigned int regno)
1135 return regno == 12;
1139 #undef TARGET_FUNCTION_VALUE
1140 #define TARGET_FUNCTION_VALUE msp430_function_value
1143 msp430_function_value (const_tree ret_type,
1144 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1145 bool outgoing ATTRIBUTE_UNUSED)
1147 return gen_rtx_REG (TYPE_MODE (ret_type), 12);
1150 #undef TARGET_LIBCALL_VALUE
1151 #define TARGET_LIBCALL_VALUE msp430_libcall_value
1154 msp430_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
1156 return gen_rtx_REG (mode, 12);
1159 /* Implements INIT_CUMULATIVE_ARGS. */
1160 void
1161 msp430_init_cumulative_args (CUMULATIVE_ARGS *ca,
1162 tree fntype ATTRIBUTE_UNUSED,
1163 rtx libname ATTRIBUTE_UNUSED,
1164 tree fndecl ATTRIBUTE_UNUSED,
1165 int n_named_args ATTRIBUTE_UNUSED)
1167 const char *fname;
1168 memset (ca, 0, sizeof(*ca));
1170 ca->can_split = 1;
1172 if (fndecl)
1173 fname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
1174 else if (libname)
1175 fname = XSTR (libname, 0);
1176 else
1177 fname = NULL;
1179 if (fname && msp430_special_register_convention_p (fname))
1180 ca->special_p = 1;
1183 /* Helper function for argument passing; this function is the common
1184 code that determines where an argument will be passed. */
1185 static void
1186 msp430_evaluate_arg (cumulative_args_t cap,
1187 machine_mode mode,
1188 const_tree type ATTRIBUTE_UNUSED,
1189 bool named)
1191 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1192 int nregs = GET_MODE_SIZE (mode);
1193 int i;
1195 ca->reg_count = 0;
1196 ca->mem_count = 0;
1198 if (!named)
1199 return;
1201 if (mode == PSImode)
1202 nregs = 1;
1203 else
1204 nregs = (nregs + 1) / 2;
1206 if (ca->special_p)
1208 /* Function is passed two DImode operands, in R8:R11 and
1209 R12:15. */
1210 ca->start_reg = 8;
1211 ca->reg_count = 4;
1212 return;
1215 switch (nregs)
1217 case 1:
1218 for (i = 0; i < 4; i++)
1219 if (! ca->reg_used [i])
1221 ca->reg_count = 1;
1222 ca->start_reg = CA_FIRST_REG + i;
1223 return;
1225 break;
1226 case 2:
1227 for (i = 0; i < 3; i++)
1228 if (! ca->reg_used [i] && ! ca->reg_used [i + 1])
1230 ca->reg_count = 2;
1231 ca->start_reg = CA_FIRST_REG + i;
1232 return;
1234 if (! ca->reg_used [3] && ca->can_split)
1236 ca->reg_count = 1;
1237 ca->mem_count = 2;
1238 ca->start_reg = CA_FIRST_REG + 3;
1239 return;
1241 break;
1242 case 3:
1243 case 4:
1244 ca->can_split = 0;
1245 if (! ca->reg_used [0]
1246 && ! ca->reg_used [1]
1247 && ! ca->reg_used [2]
1248 && ! ca->reg_used [3])
1250 ca->reg_count = 4;
1251 ca->start_reg = CA_FIRST_REG;
1252 return;
1254 break;
1258 #undef TARGET_PROMOTE_PROTOTYPES
1259 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
1261 bool
1262 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED)
1264 return false;
1267 #undef TARGET_FUNCTION_ARG
1268 #define TARGET_FUNCTION_ARG msp430_function_arg
1271 msp430_function_arg (cumulative_args_t cap,
1272 machine_mode mode,
1273 const_tree type,
1274 bool named)
1276 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1278 msp430_evaluate_arg (cap, mode, type, named);
1280 if (ca->reg_count)
1281 return gen_rtx_REG (mode, ca->start_reg);
1283 return 0;
1286 #undef TARGET_ARG_PARTIAL_BYTES
1287 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
1290 msp430_arg_partial_bytes (cumulative_args_t cap,
1291 machine_mode mode,
1292 tree type,
1293 bool named)
1295 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1297 msp430_evaluate_arg (cap, mode, type, named);
1299 if (ca->reg_count && ca->mem_count)
1300 return ca->reg_count * UNITS_PER_WORD;
1302 return 0;
1305 #undef TARGET_PASS_BY_REFERENCE
1306 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
1308 static bool
1309 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED,
1310 machine_mode mode,
1311 const_tree type,
1312 bool named ATTRIBUTE_UNUSED)
1314 return (mode == BLKmode
1315 || (type && TREE_CODE (type) == RECORD_TYPE)
1316 || (type && TREE_CODE (type) == UNION_TYPE));
1319 #undef TARGET_CALLEE_COPIES
1320 #define TARGET_CALLEE_COPIES msp430_callee_copies
1322 static bool
1323 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED,
1324 machine_mode mode ATTRIBUTE_UNUSED,
1325 const_tree type ATTRIBUTE_UNUSED,
1326 bool named ATTRIBUTE_UNUSED)
1328 return true;
1331 #undef TARGET_FUNCTION_ARG_ADVANCE
1332 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
1334 void
1335 msp430_function_arg_advance (cumulative_args_t cap,
1336 machine_mode mode,
1337 const_tree type,
1338 bool named)
1340 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1341 int i;
1343 msp430_evaluate_arg (cap, mode, type, named);
1345 if (ca->start_reg >= CA_FIRST_REG)
1346 for (i = 0; i < ca->reg_count; i ++)
1347 ca->reg_used [i + ca->start_reg - CA_FIRST_REG] = 1;
1349 ca->special_p = 0;
1352 #undef TARGET_FUNCTION_ARG_BOUNDARY
1353 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
1355 static unsigned int
1356 msp430_function_arg_boundary (machine_mode mode, const_tree type)
1358 if (mode == BLKmode
1359 && int_size_in_bytes (type) > 1)
1360 return 16;
1361 if (GET_MODE_BITSIZE (mode) > 8)
1362 return 16;
1363 return 8;
1366 #undef TARGET_RETURN_IN_MEMORY
1367 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
1369 static bool
1370 msp430_return_in_memory (const_tree ret_type, const_tree fntype ATTRIBUTE_UNUSED)
1372 machine_mode mode = TYPE_MODE (ret_type);
1374 if (mode == BLKmode
1375 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == RECORD_TYPE)
1376 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == UNION_TYPE))
1377 return true;
1379 if (GET_MODE_SIZE (mode) > 8)
1380 return true;
1382 return false;
1385 #undef TARGET_GET_RAW_ARG_MODE
1386 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
1388 static machine_mode
1389 msp430_get_raw_arg_mode (int regno)
1391 return (regno == ARG_POINTER_REGNUM) ? VOIDmode : Pmode;
1394 #undef TARGET_GET_RAW_RESULT_MODE
1395 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
1397 static machine_mode
1398 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED)
1400 return Pmode;
1403 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
1404 #define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
1406 #include "gimplify.h"
1408 static tree
1409 msp430_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
1410 gimple_seq *post_p)
1412 tree addr, t, type_size, rounded_size, valist_tmp;
1413 unsigned HOST_WIDE_INT align, boundary;
1414 bool indirect;
1416 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
1417 if (indirect)
1418 type = build_pointer_type (type);
1420 align = PARM_BOUNDARY / BITS_PER_UNIT;
1421 boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
1423 /* When we align parameter on stack for caller, if the parameter
1424 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
1425 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
1426 here with caller. */
1427 if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
1428 boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
1430 boundary /= BITS_PER_UNIT;
1432 /* Hoist the valist value into a temporary for the moment. */
1433 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
1435 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
1436 requires greater alignment, we must perform dynamic alignment. */
1437 if (boundary > align
1438 && !integer_zerop (TYPE_SIZE (type)))
1440 /* FIXME: This is where this function diverts from targhooks.c:
1441 std_gimplify_va_arg_expr(). It works, but I do not know why... */
1442 if (! POINTER_TYPE_P (type))
1444 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
1445 fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
1446 gimplify_and_add (t, pre_p);
1448 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
1449 fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
1450 valist_tmp,
1451 build_int_cst (TREE_TYPE (valist), -boundary)));
1452 gimplify_and_add (t, pre_p);
1455 else
1456 boundary = align;
1458 /* If the actual alignment is less than the alignment of the type,
1459 adjust the type accordingly so that we don't assume strict alignment
1460 when dereferencing the pointer. */
1461 boundary *= BITS_PER_UNIT;
1462 if (boundary < TYPE_ALIGN (type))
1464 type = build_variant_type_copy (type);
1465 SET_TYPE_ALIGN (type, boundary);
1468 /* Compute the rounded size of the type. */
1469 type_size = size_in_bytes (type);
1470 rounded_size = round_up (type_size, align);
1472 /* Reduce rounded_size so it's sharable with the postqueue. */
1473 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
1475 /* Get AP. */
1476 addr = valist_tmp;
1478 /* Compute new value for AP. */
1479 t = fold_build_pointer_plus (valist_tmp, rounded_size);
1480 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
1481 gimplify_and_add (t, pre_p);
1483 addr = fold_convert (build_pointer_type (type), addr);
1485 if (indirect)
1486 addr = build_va_arg_indirect_ref (addr);
1488 addr = build_va_arg_indirect_ref (addr);
1490 return addr;
1493 /* Addressing Modes */
1495 #undef TARGET_LEGITIMATE_ADDRESS_P
1496 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
1498 static bool
1499 reg_ok_for_addr (rtx r, bool strict)
1501 int rn = REGNO (r);
1503 if (strict && rn >= FIRST_PSEUDO_REGISTER)
1504 rn = reg_renumber [rn];
1505 if (strict && 0 <= rn && rn < FIRST_PSEUDO_REGISTER)
1506 return true;
1507 if (!strict)
1508 return true;
1509 return false;
1512 bool
1513 msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
1514 rtx x ATTRIBUTE_UNUSED,
1515 bool strict ATTRIBUTE_UNUSED)
1517 switch (GET_CODE (x))
1519 case MEM:
1520 return false;
1522 case PLUS:
1523 if (REG_P (XEXP (x, 0)))
1525 if (GET_MODE (x) != GET_MODE (XEXP (x, 0)))
1526 return false;
1527 if (!reg_ok_for_addr (XEXP (x, 0), strict))
1528 return false;
1529 switch (GET_CODE (XEXP (x, 1)))
1531 case CONST:
1532 case SYMBOL_REF:
1533 case CONST_INT:
1534 return true;
1535 default:
1536 return false;
1539 return false;
1541 case REG:
1542 if (!reg_ok_for_addr (x, strict))
1543 return false;
1544 /* else... */
1545 case CONST:
1546 case SYMBOL_REF:
1547 case CONST_INT:
1548 return true;
1550 default:
1551 return false;
1555 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1556 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
1558 bool
1559 msp430_addr_space_legitimate_address_p (machine_mode mode,
1560 rtx x,
1561 bool strict,
1562 addr_space_t as ATTRIBUTE_UNUSED)
1564 return msp430_legitimate_address_p (mode, x, strict);
1567 #undef TARGET_ASM_INTEGER
1568 #define TARGET_ASM_INTEGER msp430_asm_integer
1569 static bool
1570 msp430_asm_integer (rtx x, unsigned int size, int aligned_p)
1572 int c = GET_CODE (x);
1574 if (size == 3 && GET_MODE (x) == PSImode)
1575 size = 4;
1577 switch (size)
1579 case 4:
1580 if (c == SYMBOL_REF || c == CONST || c == LABEL_REF || c == CONST_INT
1581 || c == PLUS || c == MINUS)
1583 fprintf (asm_out_file, "\t.long\t");
1584 output_addr_const (asm_out_file, x);
1585 fputc ('\n', asm_out_file);
1586 return true;
1588 break;
1590 return default_assemble_integer (x, size, aligned_p);
1593 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
1594 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra
1595 static bool
1596 msp430_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED, rtx x)
1598 debug_rtx(x);
1599 return false;
1602 #undef TARGET_LEGITIMATE_CONSTANT_P
1603 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
1605 static bool
1606 msp430_legitimate_constant (machine_mode mode, rtx x)
1608 return ! CONST_INT_P (x)
1609 || mode != PSImode
1610 /* GCC does not know the width of the PSImode, so make
1611 sure that it does not try to use a constant value that
1612 is out of range. */
1613 || (INTVAL (x) < (1 << 20) && INTVAL (x) >= (HOST_WIDE_INT)(HOST_WIDE_INT_M1U << 20));
1617 #undef TARGET_RTX_COSTS
1618 #define TARGET_RTX_COSTS msp430_rtx_costs
1620 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED,
1621 machine_mode mode,
1622 int outer_code ATTRIBUTE_UNUSED,
1623 int opno ATTRIBUTE_UNUSED,
1624 int * total,
1625 bool speed ATTRIBUTE_UNUSED)
1627 int code = GET_CODE (x);
1629 switch (code)
1631 case SIGN_EXTEND:
1632 if (mode == SImode && outer_code == SET)
1634 *total = COSTS_N_INSNS (4);
1635 return true;
1637 break;
1638 case ASHIFT:
1639 case ASHIFTRT:
1640 case LSHIFTRT:
1641 if (!msp430x)
1643 *total = COSTS_N_INSNS (100);
1644 return true;
1646 break;
1648 return false;
1651 /* Function Entry and Exit */
1653 /* The MSP430 call frame looks like this:
1655 <higher addresses>
1656 +--------------------+
1658 | Stack Arguments |
1660 +--------------------+ <-- "arg pointer"
1662 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
1664 +--------------------+
1665 | SR if this func has|
1666 | been called via an |
1667 | interrupt. |
1668 +--------------------+ <-- SP before prologue, also AP
1670 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
1672 +--------------------+ <-- "frame pointer"
1674 | Locals |
1676 +--------------------+
1678 | Outgoing Args |
1680 +--------------------+ <-- SP during function
1681 <lower addresses>
1685 /* We use this to wrap all emitted insns in the prologue, so they get
1686 the "frame-related" (/f) flag set. */
1687 static rtx
1688 F (rtx x)
1690 RTX_FRAME_RELATED_P (x) = 1;
1691 return x;
1694 /* This is the one spot that decides if a register is to be saved and
1695 restored in the prologue/epilogue. */
1696 static bool
1697 msp430_preserve_reg_p (int regno)
1699 /* PC, SP, SR, and the constant generator. */
1700 if (regno <= 3)
1701 return false;
1703 /* FIXME: add interrupt, EH, etc. */
1704 if (crtl->calls_eh_return)
1705 return true;
1707 /* Shouldn't be more than the above, but just in case... */
1708 if (fixed_regs [regno])
1709 return false;
1711 /* Interrupt handlers save all registers they use, even
1712 ones which are call saved. If they call other functions
1713 then *every* register is saved. */
1714 if (msp430_is_interrupt_func ())
1715 return ! crtl->is_leaf || df_regs_ever_live_p (regno);
1717 if (!call_used_regs [regno]
1718 && df_regs_ever_live_p (regno))
1719 return true;
1721 return false;
1724 /* Compute all the frame-related fields in our machine_function
1725 structure. */
1726 static void
1727 msp430_compute_frame_info (void)
1729 int i;
1731 cfun->machine->computed = 1;
1732 cfun->machine->framesize_regs = 0;
1733 cfun->machine->framesize_locals = get_frame_size ();
1734 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
1736 for (i = 0; i < ARG_POINTER_REGNUM; i ++)
1737 if (msp430_preserve_reg_p (i))
1739 cfun->machine->need_to_save [i] = 1;
1740 cfun->machine->framesize_regs += (TARGET_LARGE ? 4 : 2);
1742 else
1743 cfun->machine->need_to_save [i] = 0;
1745 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
1746 cfun->machine->framesize_locals ++;
1748 cfun->machine->framesize = (cfun->machine->framesize_regs
1749 + cfun->machine->framesize_locals
1750 + cfun->machine->framesize_outgoing);
1753 /* Attribute Handling. */
1755 const char * const ATTR_INTR = "interrupt";
1756 const char * const ATTR_WAKEUP = "wakeup";
1757 const char * const ATTR_NAKED = "naked";
1758 const char * const ATTR_REENT = "reentrant";
1759 const char * const ATTR_CRIT = "critical";
1760 const char * const ATTR_LOWER = "lower";
1761 const char * const ATTR_UPPER = "upper";
1762 const char * const ATTR_EITHER = "either";
1763 const char * const ATTR_NOINIT = "noinit";
1764 const char * const ATTR_PERSIST = "persistent";
1766 static inline bool
1767 has_attr (const char * attr, tree decl)
1769 if (decl == NULL_TREE)
1770 return false;
1771 return lookup_attribute (attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
1774 static bool
1775 is_interrupt_func (tree decl = current_function_decl)
1777 return has_attr (ATTR_INTR, decl);
1780 /* Returns true if the current function has the "interrupt" attribute. */
1782 bool
1783 msp430_is_interrupt_func (void)
1785 return is_interrupt_func (current_function_decl);
1788 static bool
1789 is_wakeup_func (tree decl = current_function_decl)
1791 return is_interrupt_func (decl) && has_attr (ATTR_WAKEUP, decl);
1794 static inline bool
1795 is_naked_func (tree decl = current_function_decl)
1797 return has_attr (ATTR_NAKED, decl);
1800 static inline bool
1801 is_reentrant_func (tree decl = current_function_decl)
1803 return has_attr (ATTR_REENT, decl);
1806 static inline bool
1807 is_critical_func (tree decl = current_function_decl)
1809 return has_attr (ATTR_CRIT, decl);
1812 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
1813 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS msp430_allocate_stack_slots_for_args
1815 static bool
1816 msp430_allocate_stack_slots_for_args (void)
1818 /* Naked functions should not allocate stack slots for arguments. */
1819 return ! is_naked_func ();
1822 /* Verify MSP430 specific attributes. */
1823 #define TREE_NAME_EQ(NAME, STR) (strcmp (IDENTIFIER_POINTER (NAME), (STR)) == 0)
1825 static tree
1826 msp430_attr (tree * node,
1827 tree name,
1828 tree args,
1829 int flags ATTRIBUTE_UNUSED,
1830 bool * no_add_attrs)
1832 gcc_assert (DECL_P (* node));
1834 if (args != NULL)
1836 /* Only the interrupt attribute takes an argument. */
1837 gcc_assert (TREE_NAME_EQ (name, ATTR_INTR));
1839 tree value = TREE_VALUE (args);
1841 switch (TREE_CODE (value))
1843 case STRING_CST:
1844 if ( strcmp (TREE_STRING_POINTER (value), "reset")
1845 && strcmp (TREE_STRING_POINTER (value), "nmi")
1846 && strcmp (TREE_STRING_POINTER (value), "watchdog"))
1847 /* Allow the attribute to be added - the linker script
1848 being used may still recognise this name. */
1849 warning (OPT_Wattributes,
1850 "unrecognised interrupt vector argument of %qE attribute",
1851 name);
1852 break;
1854 case INTEGER_CST:
1855 if (wi::gtu_p (value, 63))
1856 /* Allow the attribute to be added - the linker script
1857 being used may still recognise this value. */
1858 warning (OPT_Wattributes,
1859 "numeric argument of %qE attribute must be in range 0..63",
1860 name);
1861 break;
1863 default:
1864 warning (OPT_Wattributes,
1865 "argument of %qE attribute is not a string constant or number",
1866 name);
1867 *no_add_attrs = true;
1868 break;
1872 const char * message = NULL;
1874 if (TREE_CODE (* node) != FUNCTION_DECL)
1876 message = "%qE attribute only applies to functions";
1878 else if (TREE_NAME_EQ (name, ATTR_INTR))
1880 if (TREE_CODE (TREE_TYPE (* node)) == FUNCTION_TYPE
1881 && ! VOID_TYPE_P (TREE_TYPE (TREE_TYPE (* node))))
1882 message = "interrupt handlers must be void";
1884 if (! TREE_PUBLIC (* node))
1885 message = "interrupt handlers cannot be static";
1887 else if (TREE_NAME_EQ (name, ATTR_REENT))
1889 if (is_naked_func (* node))
1890 message = "naked functions cannot be reentrant";
1891 else if (is_critical_func (* node))
1892 message = "critical functions cannot be reentrant";
1894 else if (TREE_NAME_EQ (name, ATTR_CRIT))
1896 if (is_naked_func (* node))
1897 message = "naked functions cannot be critical";
1898 else if (is_reentrant_func (* node))
1899 message = "reentrant functions cannot be critical";
1901 else if (TREE_NAME_EQ (name, ATTR_NAKED))
1903 if (is_critical_func (* node))
1904 message = "critical functions cannot be naked";
1905 else if (is_reentrant_func (* node))
1906 message = "reentrant functions cannot be naked";
1909 if (message)
1911 warning (OPT_Wattributes, message, name);
1912 * no_add_attrs = true;
1915 return NULL_TREE;
1918 static tree
1919 msp430_section_attr (tree * node,
1920 tree name,
1921 tree args,
1922 int flags ATTRIBUTE_UNUSED,
1923 bool * no_add_attrs ATTRIBUTE_UNUSED)
1925 gcc_assert (DECL_P (* node));
1926 gcc_assert (args == NULL);
1928 const char * message = NULL;
1930 if (TREE_NAME_EQ (name, ATTR_UPPER))
1932 if (has_attr (ATTR_LOWER, * node))
1933 message = "already marked with 'lower' attribute";
1934 else if (has_attr (ATTR_EITHER, * node))
1935 message = "already marked with 'either' attribute";
1936 else if (! msp430x)
1937 message = "upper attribute needs a 430X cpu";
1939 else if (TREE_NAME_EQ (name, ATTR_LOWER))
1941 if (has_attr (ATTR_UPPER, * node))
1942 message = "already marked with 'upper' attribute";
1943 else if (has_attr (ATTR_EITHER, * node))
1944 message = "already marked with 'either' attribute";
1946 else
1948 gcc_assert (TREE_NAME_EQ (name, ATTR_EITHER));
1950 if (has_attr (ATTR_LOWER, * node))
1951 message = "already marked with 'lower' attribute";
1952 else if (has_attr (ATTR_UPPER, * node))
1953 message = "already marked with 'upper' attribute";
1956 if (message)
1958 warning (OPT_Wattributes, message, name);
1959 * no_add_attrs = true;
1962 return NULL_TREE;
1965 static tree
1966 msp430_data_attr (tree * node,
1967 tree name,
1968 tree args,
1969 int flags ATTRIBUTE_UNUSED,
1970 bool * no_add_attrs ATTRIBUTE_UNUSED)
1972 const char * message = NULL;
1974 gcc_assert (DECL_P (* node));
1975 gcc_assert (args == NULL);
1977 if (TREE_CODE (* node) != VAR_DECL)
1978 message = "%qE attribute only applies to variables";
1980 if (DECL_SECTION_NAME (* node))
1981 message = "%qE attribute cannot be applied to variables with specific sections";
1983 /* If this var is thought to be common, then change this. Common variables
1984 are assigned to sections before the backend has a chance to process them. */
1985 if (DECL_COMMON (* node))
1986 DECL_COMMON (* node) = 0;
1988 if (message)
1990 warning (OPT_Wattributes, message, name);
1991 * no_add_attrs = true;
1994 return NULL_TREE;
1998 #undef TARGET_ATTRIBUTE_TABLE
1999 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
2001 /* Table of MSP430-specific attributes. */
2002 const struct attribute_spec msp430_attribute_table[] =
2004 /* Name min_num_args type_req, affects_type_identity
2005 max_num_args, fn_type_req
2006 decl_req handler. */
2007 { ATTR_INTR, 0, 1, true, false, false, msp430_attr, false },
2008 { ATTR_NAKED, 0, 0, true, false, false, msp430_attr, false },
2009 { ATTR_REENT, 0, 0, true, false, false, msp430_attr, false },
2010 { ATTR_CRIT, 0, 0, true, false, false, msp430_attr, false },
2011 { ATTR_WAKEUP, 0, 0, true, false, false, msp430_attr, false },
2013 { ATTR_LOWER, 0, 0, true, false, false, msp430_section_attr, false },
2014 { ATTR_UPPER, 0, 0, true, false, false, msp430_section_attr, false },
2015 { ATTR_EITHER, 0, 0, true, false, false, msp430_section_attr, false },
2017 { ATTR_NOINIT, 0, 0, true, false, false, msp430_data_attr, false },
2018 { ATTR_PERSIST, 0, 0, true, false, false, msp430_data_attr, false },
2020 { NULL, 0, 0, false, false, false, NULL, false }
2023 #undef TARGET_ASM_FUNCTION_PROLOGUE
2024 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
2026 static void
2027 msp430_start_function (FILE *outfile, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
2029 int r, n;
2031 fprintf (outfile, "; start of function\n");
2033 if (DECL_ATTRIBUTES (current_function_decl) != NULL_TREE)
2035 fprintf (outfile, "; attributes: ");
2036 if (is_naked_func ())
2037 fprintf (outfile, "naked ");
2038 if (msp430_is_interrupt_func ())
2039 fprintf (outfile, "interrupt ");
2040 if (is_reentrant_func ())
2041 fprintf (outfile, "reentrant ");
2042 if (is_critical_func ())
2043 fprintf (outfile, "critical ");
2044 if (is_wakeup_func ())
2045 fprintf (outfile, "wakeup ");
2046 fprintf (outfile, "\n");
2049 fprintf (outfile, "; framesize_regs: %d\n", cfun->machine->framesize_regs);
2050 fprintf (outfile, "; framesize_locals: %d\n", cfun->machine->framesize_locals);
2051 fprintf (outfile, "; framesize_outgoing: %d\n", cfun->machine->framesize_outgoing);
2052 fprintf (outfile, "; framesize: %d\n", cfun->machine->framesize);
2053 fprintf (outfile, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM));
2054 fprintf (outfile, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM));
2056 n = 0;
2057 fprintf (outfile, "; saved regs:");
2058 for (r = 0; r < ARG_POINTER_REGNUM; r++)
2059 if (cfun->machine->need_to_save [r])
2061 fprintf (outfile, " %s", reg_names [r]);
2062 n = 1;
2064 if (n == 0)
2065 fprintf (outfile, "(none)");
2066 fprintf (outfile, "\n");
2069 /* Common code to change the stack pointer. */
2070 static void
2071 increment_stack (HOST_WIDE_INT amount)
2073 rtx inc;
2074 rtx sp = stack_pointer_rtx;
2076 if (amount == 0)
2077 return;
2079 if (amount < 0)
2081 inc = GEN_INT (- amount);
2082 if (TARGET_LARGE)
2083 F (emit_insn (gen_subpsi3 (sp, sp, inc)));
2084 else
2085 F (emit_insn (gen_subhi3 (sp, sp, inc)));
2087 else
2089 inc = GEN_INT (amount);
2090 if (TARGET_LARGE)
2091 emit_insn (gen_addpsi3 (sp, sp, inc));
2092 else
2093 emit_insn (gen_addhi3 (sp, sp, inc));
2097 void
2098 msp430_start_function (FILE *file, const char *name, tree decl)
2100 tree int_attr;
2102 int_attr = lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl));
2103 if (int_attr != NULL_TREE)
2105 tree intr_vector = TREE_VALUE (int_attr);
2107 if (intr_vector != NULL_TREE)
2109 char buf[101];
2111 /* Interrupt vector sections should be unique, but use of weak
2112 functions implies multiple definitions. */
2113 if (DECL_WEAK (decl))
2115 error ("argument to interrupt attribute is unsupported for weak functions");
2118 intr_vector = TREE_VALUE (intr_vector);
2120 /* The interrupt attribute has a vector value. Turn this into a
2121 section name, switch to that section and put the address of
2122 the current function into that vector slot. Note msp430_attr()
2123 has already verified the vector name for us. */
2124 if (TREE_CODE (intr_vector) == STRING_CST)
2125 sprintf (buf, "__interrupt_vector_%.80s",
2126 TREE_STRING_POINTER (intr_vector));
2127 else /* TREE_CODE (intr_vector) == INTEGER_CST */
2128 sprintf (buf, "__interrupt_vector_%u",
2129 (unsigned int) TREE_INT_CST_LOW (intr_vector));
2131 switch_to_section (get_section (buf, SECTION_CODE, decl));
2132 fputs ("\t.word\t", file);
2133 assemble_name (file, name);
2134 fputc ('\n', file);
2135 fputc ('\t', file);
2139 switch_to_section (function_section (decl));
2140 ASM_OUTPUT_TYPE_DIRECTIVE(file, name, "function");
2141 ASM_OUTPUT_FUNCTION_LABEL (file, name, decl);
2144 static const char * const lower_prefix = ".lower";
2145 static const char * const upper_prefix = ".upper";
2146 static const char * const either_prefix = ".either";
2148 /* Generate a prefix for a section name, based upon
2149 the region into which the object should be placed. */
2151 static const char *
2152 gen_prefix (tree decl)
2154 if (DECL_ONE_ONLY (decl))
2155 return NULL;
2157 /* If the user has specified a particular section then do not use any prefix. */
2158 if (has_attr ("section", decl))
2159 return NULL;
2161 /* If the object has __attribute__((lower)) then use the ".lower." prefix. */
2162 if (has_attr (ATTR_LOWER, decl))
2163 return lower_prefix;
2165 /* If we are compiling for the MSP430 then we do not support the upper region. */
2166 if (! msp430x)
2167 return NULL;
2169 if (has_attr (ATTR_UPPER, decl))
2170 return upper_prefix;
2172 if (has_attr (ATTR_EITHER, decl))
2173 return either_prefix;
2175 if (TREE_CODE (decl) == FUNCTION_DECL)
2177 if (msp430_code_region == MSP430_REGION_LOWER)
2178 return lower_prefix;
2180 if (msp430_code_region == MSP430_REGION_UPPER)
2181 return upper_prefix;
2183 if (msp430_code_region == MSP430_REGION_EITHER)
2184 return either_prefix;
2186 else
2188 if (msp430_data_region == MSP430_REGION_LOWER)
2189 return lower_prefix;
2191 if (msp430_data_region == MSP430_REGION_UPPER)
2192 return upper_prefix;
2194 if (msp430_data_region == MSP430_REGION_EITHER)
2195 return either_prefix;
2198 return NULL;
2201 static section * noinit_section;
2202 static section * persist_section;
2204 #undef TARGET_ASM_INIT_SECTIONS
2205 #define TARGET_ASM_INIT_SECTIONS msp430_init_sections
2207 static void
2208 msp430_init_sections (void)
2210 noinit_section = get_unnamed_section (0, output_section_asm_op, ".section .noinit,\"aw\"");
2211 persist_section = get_unnamed_section (0, output_section_asm_op, ".section .persistent,\"aw\"");
2214 #undef TARGET_ASM_SELECT_SECTION
2215 #define TARGET_ASM_SELECT_SECTION msp430_select_section
2217 static section *
2218 msp430_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
2220 gcc_assert (decl != NULL_TREE);
2222 if (TREE_CODE (decl) == STRING_CST
2223 || TREE_CODE (decl) == CONSTRUCTOR
2224 || TREE_CODE (decl) == INTEGER_CST
2225 || TREE_CODE (decl) == VECTOR_CST
2226 || TREE_CODE (decl) == COMPLEX_CST)
2227 return default_select_section (decl, reloc, align);
2229 /* In large mode we must make sure that interrupt handlers are put into
2230 low memory as the vector table only accepts 16-bit addresses. */
2231 if (TARGET_LARGE && TREE_CODE (decl) == FUNCTION_DECL && is_interrupt_func (decl))
2232 return get_section (".lowtext", SECTION_CODE | SECTION_WRITE , decl);
2234 const char * prefix = gen_prefix (decl);
2235 if (prefix == NULL)
2237 if (TREE_CODE (decl) == FUNCTION_DECL)
2238 return text_section;
2239 else if (has_attr (ATTR_NOINIT, decl))
2240 return noinit_section;
2241 else if (has_attr (ATTR_PERSIST, decl))
2242 return persist_section;
2243 else
2244 return default_select_section (decl, reloc, align);
2247 const char * sec;
2248 switch (categorize_decl_for_section (decl, reloc))
2250 case SECCAT_TEXT: sec = ".text"; break;
2251 case SECCAT_DATA: sec = ".data"; break;
2252 case SECCAT_BSS: sec = ".bss"; break;
2253 case SECCAT_RODATA: sec = ".rodata"; break;
2255 case SECCAT_RODATA_MERGE_STR:
2256 case SECCAT_RODATA_MERGE_STR_INIT:
2257 case SECCAT_RODATA_MERGE_CONST:
2258 case SECCAT_SRODATA:
2259 case SECCAT_DATA_REL:
2260 case SECCAT_DATA_REL_LOCAL:
2261 case SECCAT_DATA_REL_RO:
2262 case SECCAT_DATA_REL_RO_LOCAL:
2263 case SECCAT_SDATA:
2264 case SECCAT_SBSS:
2265 case SECCAT_TDATA:
2266 case SECCAT_TBSS:
2267 return default_select_section (decl, reloc, align);
2269 default:
2270 gcc_unreachable ();
2273 const char * dec_name = DECL_SECTION_NAME (decl);
2274 char * name = ACONCAT ((prefix, sec, dec_name, NULL));
2276 return get_named_section (decl, name, 0);
2279 #undef TARGET_ASM_FUNCTION_SECTION
2280 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
2282 static section *
2283 msp430_function_section (tree decl, enum node_frequency freq, bool startup, bool exit)
2285 const char * name;
2287 gcc_assert (DECL_SECTION_NAME (decl) != NULL);
2288 name = DECL_SECTION_NAME (decl);
2290 const char * prefix = gen_prefix (decl);
2291 if (prefix == NULL
2292 || strncmp (name, prefix, strlen (prefix)) == 0)
2293 return default_function_section (decl, freq, startup, exit);
2295 name = ACONCAT ((prefix, name, NULL));
2296 return get_named_section (decl, name, 0);
2299 #undef TARGET_SECTION_TYPE_FLAGS
2300 #define TARGET_SECTION_TYPE_FLAGS msp430_section_type_flags
2302 unsigned int
2303 msp430_section_type_flags (tree decl, const char * name, int reloc)
2305 if (strncmp (name, lower_prefix, strlen (lower_prefix)) == 0)
2306 name += strlen (lower_prefix);
2307 else if (strncmp (name, upper_prefix, strlen (upper_prefix)) == 0)
2308 name += strlen (upper_prefix);
2309 else if (strncmp (name, either_prefix, strlen (either_prefix)) == 0)
2310 name += strlen (either_prefix);
2311 else if (strcmp (name, ".noinit") == 0)
2312 return SECTION_WRITE | SECTION_BSS | SECTION_NOTYPE;
2313 else if (strcmp (name, ".persistent") == 0)
2314 return SECTION_WRITE | SECTION_NOTYPE;
2316 return default_section_type_flags (decl, name, reloc);
2319 #undef TARGET_ASM_UNIQUE_SECTION
2320 #define TARGET_ASM_UNIQUE_SECTION msp430_unique_section
2322 static void
2323 msp430_unique_section (tree decl, int reloc)
2325 gcc_assert (decl != NULL_TREE);
2327 /* In large mode we must make sure that interrupt handlers are put into
2328 low memory as the vector table only accepts 16-bit addresses. */
2329 if (TARGET_LARGE && TREE_CODE (decl) == FUNCTION_DECL && is_interrupt_func (decl))
2331 set_decl_section_name (decl, ".lowtext");
2332 return;
2335 default_unique_section (decl, reloc);
2337 const char * prefix;
2339 if ( TREE_CODE (decl) == STRING_CST
2340 || TREE_CODE (decl) == CONSTRUCTOR
2341 || TREE_CODE (decl) == INTEGER_CST
2342 || TREE_CODE (decl) == VECTOR_CST
2343 || TREE_CODE (decl) == COMPLEX_CST
2344 || (prefix = gen_prefix (decl)) == NULL
2346 return;
2348 const char * dec_name = DECL_SECTION_NAME (decl);
2349 char * name = ACONCAT ((prefix, dec_name, NULL));
2351 set_decl_section_name (decl, name);
2354 /* Emit a declaration of a common symbol.
2355 If a data region is in use then put the symbol into the
2356 equivalent .bss section instead. */
2358 void
2359 msp430_output_aligned_decl_common (FILE * stream,
2360 const tree decl,
2361 const char * name,
2362 unsigned HOST_WIDE_INT size,
2363 unsigned int align)
2365 if (msp430_data_region == MSP430_REGION_ANY)
2367 fprintf (stream, COMMON_ASM_OP);
2368 assemble_name (stream, name);
2369 fprintf (stream, "," HOST_WIDE_INT_PRINT_UNSIGNED",%u\n",
2370 size, align / BITS_PER_UNIT);
2372 else
2374 section * sec;
2376 if (decl)
2377 sec = msp430_select_section (decl, 0, align);
2378 else
2379 switch (msp430_data_region)
2381 case MSP430_REGION_UPPER: sec = get_named_section (NULL, ".upper.bss", 0); break;
2382 case MSP430_REGION_LOWER: sec = get_named_section (NULL, ".lower.bss", 0); break;
2383 case MSP430_REGION_EITHER: sec = get_named_section (NULL, ".either.bss", 0); break;
2384 default:
2385 gcc_unreachable ();
2387 gcc_assert (sec != NULL);
2389 switch_to_section (sec);
2390 ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
2391 targetm.asm_out.globalize_label (stream, name);
2392 ASM_WEAKEN_LABEL (stream, name);
2393 ASM_OUTPUT_LABEL (stream, name);
2394 ASM_OUTPUT_SKIP (stream, size ? size : 1);
2398 bool
2399 msp430_do_not_relax_short_jumps (void)
2401 /* When placing code into "either" low or high memory we do not want the linker
2402 to grow the size of sections, which it can do if it is encounters a branch to
2403 a label that is too far away. So we tell the cbranch patterns to avoid using
2404 short jumps when there is a chance that the instructions will end up in a low
2405 section. */
2406 return
2407 msp430_code_region == MSP430_REGION_EITHER
2408 || msp430_code_region == MSP430_REGION_LOWER
2409 || has_attr (ATTR_EITHER, current_function_decl)
2410 || has_attr (ATTR_LOWER, current_function_decl);
2413 enum msp430_builtin
2415 MSP430_BUILTIN_BIC_SR,
2416 MSP430_BUILTIN_BIS_SR,
2417 MSP430_BUILTIN_DELAY_CYCLES,
2418 MSP430_BUILTIN_max
2421 static GTY(()) tree msp430_builtins [(int) MSP430_BUILTIN_max];
2423 static void
2424 msp430_init_builtins (void)
2426 tree void_ftype_int = build_function_type_list (void_type_node, integer_type_node, NULL);
2427 tree void_ftype_longlong = build_function_type_list (void_type_node, long_long_integer_type_node, NULL);
2429 msp430_builtins[MSP430_BUILTIN_BIC_SR] =
2430 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int,
2431 MSP430_BUILTIN_BIC_SR, BUILT_IN_MD, NULL, NULL_TREE);
2433 msp430_builtins[MSP430_BUILTIN_BIS_SR] =
2434 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int,
2435 MSP430_BUILTIN_BIS_SR, BUILT_IN_MD, NULL, NULL_TREE);
2437 msp430_builtins[MSP430_BUILTIN_DELAY_CYCLES] =
2438 add_builtin_function ( "__delay_cycles", void_ftype_longlong,
2439 MSP430_BUILTIN_DELAY_CYCLES, BUILT_IN_MD, NULL, NULL_TREE);
2442 static tree
2443 msp430_builtin_decl (unsigned code, bool initialize ATTRIBUTE_UNUSED)
2445 switch (code)
2447 case MSP430_BUILTIN_BIC_SR:
2448 case MSP430_BUILTIN_BIS_SR:
2449 case MSP430_BUILTIN_DELAY_CYCLES:
2450 return msp430_builtins[code];
2451 default:
2452 return error_mark_node;
2456 /* These constants are really register reads, which are faster than
2457 regular constants. */
2458 static int
2459 cg_magic_constant (HOST_WIDE_INT c)
2461 switch (c)
2463 case 0xffff:
2464 case -1:
2465 case 0:
2466 case 1:
2467 case 2:
2468 case 4:
2469 case 8:
2470 return 1;
2471 default:
2472 return 0;
2476 static rtx
2477 msp430_expand_delay_cycles (rtx arg)
2479 HOST_WIDE_INT i, c, n;
2480 /* extra cycles for MSP430X instructions */
2481 #define CYCX(M,X) (msp430x ? (X) : (M))
2483 if (GET_CODE (arg) != CONST_INT)
2485 error ("__delay_cycles() only takes constant arguments");
2486 return NULL_RTX;
2489 c = INTVAL (arg);
2491 if (HOST_BITS_PER_WIDE_INT > 32)
2493 if (c < 0)
2495 error ("__delay_cycles only takes non-negative cycle counts.");
2496 return NULL_RTX;
2500 emit_insn (gen_delay_cycles_start (arg));
2502 /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
2503 if (c > 3 * 0xffff + CYCX (7, 10))
2505 n = c;
2506 /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
2507 if (c >= 0x10000 * 7 + CYCX (14, 16))
2509 i = 0x10000;
2510 c -= CYCX (14, 16) + 7 * 0x10000;
2511 i += c / 4;
2512 c %= 4;
2513 if ((unsigned long long) i > 0xffffffffULL)
2515 error ("__delay_cycles is limited to 32-bit loop counts.");
2516 return NULL_RTX;
2519 else
2521 i = (c - CYCX (14, 16)) / 7;
2522 c -= CYCX (14, 16) + i * 7;
2525 if (cg_magic_constant (i & 0xffff))
2526 c ++;
2527 if (cg_magic_constant ((i >> 16) & 0xffff))
2528 c ++;
2530 if (msp430x)
2531 emit_insn (gen_delay_cycles_32x (GEN_INT (i), GEN_INT (n - c)));
2532 else
2533 emit_insn (gen_delay_cycles_32 (GEN_INT (i), GEN_INT (n - c)));
2536 /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
2537 if (c > 12)
2539 n = c;
2540 i = (c - CYCX (7, 10)) / 3;
2541 c -= CYCX (7, 10) + i * 3;
2543 if (cg_magic_constant (i))
2544 c ++;
2546 if (msp430x)
2547 emit_insn (gen_delay_cycles_16x (GEN_INT (i), GEN_INT (n - c)));
2548 else
2549 emit_insn (gen_delay_cycles_16 (GEN_INT (i), GEN_INT (n - c)));
2552 while (c > 1)
2554 emit_insn (gen_delay_cycles_2 ());
2555 c -= 2;
2558 if (c)
2560 emit_insn (gen_delay_cycles_1 ());
2561 c -= 1;
2564 emit_insn (gen_delay_cycles_end (arg));
2566 return NULL_RTX;
2569 static rtx
2570 msp430_expand_builtin (tree exp,
2571 rtx target ATTRIBUTE_UNUSED,
2572 rtx subtarget ATTRIBUTE_UNUSED,
2573 machine_mode mode ATTRIBUTE_UNUSED,
2574 int ignore ATTRIBUTE_UNUSED)
2576 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
2577 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2578 rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
2580 if (fcode == MSP430_BUILTIN_DELAY_CYCLES)
2581 return msp430_expand_delay_cycles (arg1);
2583 if (! msp430_is_interrupt_func ())
2585 error ("MSP430 builtin functions only work inside interrupt handlers");
2586 return NULL_RTX;
2589 if (! REG_P (arg1) && ! CONSTANT_P (arg1))
2590 arg1 = force_reg (mode, arg1);
2592 switch (fcode)
2594 case MSP430_BUILTIN_BIC_SR: emit_insn (gen_bic_SR (arg1)); break;
2595 case MSP430_BUILTIN_BIS_SR: emit_insn (gen_bis_SR (arg1)); break;
2596 default:
2597 internal_error ("bad builtin code");
2598 break;
2600 return NULL_RTX;
2603 #undef TARGET_INIT_BUILTINS
2604 #define TARGET_INIT_BUILTINS msp430_init_builtins
2606 #undef TARGET_EXPAND_BUILTIN
2607 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
2609 #undef TARGET_BUILTIN_DECL
2610 #define TARGET_BUILTIN_DECL msp430_builtin_decl
2612 void
2613 msp430_expand_prologue (void)
2615 int i, j;
2616 int fs;
2617 /* Always use stack_pointer_rtx instead of calling
2618 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
2619 that there is a single rtx representing the stack pointer,
2620 namely stack_pointer_rtx, and uses == to recognize it. */
2621 rtx sp = stack_pointer_rtx;
2622 rtx p;
2624 if (is_naked_func ())
2626 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2627 examines the output of the gen_prologue() function. */
2628 emit_insn (gen_rtx_CLOBBER (VOIDmode, GEN_INT (0)));
2629 return;
2632 emit_insn (gen_prologue_start_marker ());
2634 if (is_critical_func ())
2636 emit_insn (gen_push_intr_state ());
2637 emit_insn (gen_disable_interrupts ());
2639 else if (is_reentrant_func ())
2640 emit_insn (gen_disable_interrupts ());
2642 if (!cfun->machine->computed)
2643 msp430_compute_frame_info ();
2645 if (flag_stack_usage_info)
2646 current_function_static_stack_size = cfun->machine->framesize;
2648 if (crtl->args.pretend_args_size)
2650 rtx note;
2652 gcc_assert (crtl->args.pretend_args_size == 2);
2654 p = emit_insn (gen_grow_and_swap ());
2656 /* Document the stack decrement... */
2657 note = F (gen_rtx_SET (stack_pointer_rtx,
2658 gen_rtx_MINUS (Pmode, stack_pointer_rtx, GEN_INT (2))));
2659 add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
2661 /* ...and the establishment of a new location for the return address. */
2662 note = F (gen_rtx_SET (gen_rtx_MEM (Pmode,
2663 gen_rtx_PLUS (Pmode,
2664 stack_pointer_rtx,
2665 GEN_INT (-2))),
2666 pc_rtx));
2667 add_reg_note (p, REG_CFA_OFFSET, note);
2668 F (p);
2671 for (i = 15; i >= 4; i--)
2672 if (cfun->machine->need_to_save [i])
2674 int seq, count;
2675 rtx note;
2677 for (seq = i - 1; seq >= 4 && cfun->machine->need_to_save[seq]; seq --)
2679 count = i - seq;
2681 if (msp430x)
2683 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
2684 p = F (emit_insn (gen_pushm (gen_rtx_REG (Pmode, i),
2685 GEN_INT (count))));
2687 note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1));
2689 XVECEXP (note, 0, 0)
2690 = F (gen_rtx_SET (stack_pointer_rtx,
2691 gen_rtx_PLUS (Pmode,
2692 stack_pointer_rtx,
2693 GEN_INT (count * (TARGET_LARGE ? -4 : -2)))));
2695 /* *sp-- = R[i-j] */
2696 /* sp+N R10
2698 sp R4 */
2699 for (j = 0; j < count; j ++)
2701 rtx addr;
2702 int ofs = (count - j - 1) * (TARGET_LARGE ? 4 : 2);
2704 if (ofs)
2705 addr = gen_rtx_PLUS (Pmode, sp, GEN_INT (ofs));
2706 else
2707 addr = stack_pointer_rtx;
2709 XVECEXP (note, 0, j + 1) =
2710 F (gen_rtx_SET (gen_rtx_MEM (Pmode, addr),
2711 gen_rtx_REG (Pmode, i - j)) );
2714 add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
2715 i -= count - 1;
2717 else
2718 F (emit_insn (gen_push (gen_rtx_REG (Pmode, i))));
2721 if (frame_pointer_needed)
2722 F (emit_move_insn (gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM), sp));
2724 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
2726 increment_stack (- fs);
2728 emit_insn (gen_prologue_end_marker ());
2731 void
2732 msp430_expand_epilogue (int is_eh)
2734 int i;
2735 int fs;
2736 int helper_n = 0;
2738 if (is_naked_func ())
2740 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2741 examines the output of the gen_epilogue() function. */
2742 emit_insn (gen_rtx_CLOBBER (VOIDmode, GEN_INT (0)));
2743 return;
2746 if (cfun->machine->need_to_save [10])
2748 /* Check for a helper function. */
2749 helper_n = 7; /* For when the loop below never sees a match. */
2750 for (i = 9; i >= 4; i--)
2751 if (!cfun->machine->need_to_save [i])
2753 helper_n = 10 - i;
2754 for (; i >= 4; i--)
2755 if (cfun->machine->need_to_save [i])
2757 helper_n = 0;
2758 break;
2760 break;
2764 emit_insn (gen_epilogue_start_marker ());
2766 if (cfun->decl && strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun->decl)), "main") == 0)
2767 emit_insn (gen_msp430_refsym_need_exit ());
2769 if (is_wakeup_func ())
2770 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
2771 status register current residing on the stack. When this function
2772 executes its RETI instruction the SR will be updated with this saved
2773 value, thus ensuring that the processor is woken up from any low power
2774 state in which it may be residing. */
2775 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
2777 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
2779 increment_stack (fs);
2781 if (is_eh)
2783 /* We need to add the right "SP" register save just after the
2784 regular ones, so that when we pop it off we're in the EH
2785 return frame, not this one. This overwrites our own return
2786 address, but we're not going to be returning anyway. */
2787 rtx r12 = gen_rtx_REG (Pmode, 12);
2788 rtx (*addPmode)(rtx, rtx, rtx) = TARGET_LARGE ? gen_addpsi3 : gen_addhi3;
2790 /* R12 will hold the new SP. */
2791 i = cfun->machine->framesize_regs;
2792 emit_move_insn (r12, stack_pointer_rtx);
2793 emit_insn (addPmode (r12, r12, EH_RETURN_STACKADJ_RTX));
2794 emit_insn (addPmode (r12, r12, GEN_INT (i)));
2795 emit_move_insn (gen_rtx_MEM (Pmode, plus_constant (Pmode, stack_pointer_rtx, i)), r12);
2798 for (i = 4; i <= 15; i++)
2799 if (cfun->machine->need_to_save [i])
2801 int seq, count;
2803 for (seq = i + 1; seq <= 15 && cfun->machine->need_to_save[seq]; seq ++)
2805 count = seq - i;
2807 if (msp430x)
2809 /* Note: With TARGET_LARGE we still use
2810 POPM as POPX.A is two bytes bigger. */
2811 emit_insn (gen_popm (stack_pointer_rtx, GEN_INT (seq - 1),
2812 GEN_INT (count)));
2813 i += count - 1;
2815 else if (i == 11 - helper_n
2816 && ! msp430_is_interrupt_func ()
2817 && ! is_reentrant_func ()
2818 && ! is_critical_func ()
2819 && crtl->args.pretend_args_size == 0
2820 /* Calling the helper takes as many bytes as the POP;RET sequence. */
2821 && helper_n > 1
2822 && !is_eh)
2824 emit_insn (gen_epilogue_helper (GEN_INT (helper_n)));
2825 return;
2827 else
2828 emit_insn (gen_pop (gen_rtx_REG (Pmode, i)));
2831 if (is_eh)
2833 /* Also pop SP, which puts us into the EH return frame. Except
2834 that you can't "pop" sp, you have to just load it off the
2835 stack. */
2836 emit_move_insn (stack_pointer_rtx, gen_rtx_MEM (Pmode, stack_pointer_rtx));
2839 if (crtl->args.pretend_args_size)
2840 emit_insn (gen_swap_and_shrink ());
2842 if (is_critical_func ())
2843 emit_insn (gen_pop_intr_state ());
2844 else if (is_reentrant_func ())
2845 emit_insn (gen_enable_interrupts ());
2847 emit_jump_insn (gen_msp_return ());
2850 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
2851 m32c_emit_eh_epilogue. */
2853 msp430_eh_return_stackadj_rtx (void)
2855 if (!cfun->machine->eh_stack_adjust)
2857 rtx sa;
2859 sa = gen_rtx_REG (Pmode, 15);
2860 cfun->machine->eh_stack_adjust = sa;
2862 return cfun->machine->eh_stack_adjust;
2865 /* This function is called before reload, to "fix" the stack in
2866 preparation for an EH return. */
2867 void
2868 msp430_expand_eh_return (rtx eh_handler)
2870 /* These are all Pmode */
2871 rtx ap, sa, ra, tmp;
2873 ap = arg_pointer_rtx;
2874 sa = msp430_eh_return_stackadj_rtx ();
2875 ra = eh_handler;
2877 tmp = ap;
2878 tmp = gen_rtx_PLUS (Pmode, ap, sa);
2879 tmp = plus_constant (Pmode, tmp, TARGET_LARGE ? -4 : -2);
2880 tmp = gen_rtx_MEM (Pmode, tmp);
2881 emit_move_insn (tmp, ra);
2884 #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
2885 #define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
2886 void
2887 msp430_init_dwarf_reg_sizes_extra (tree address)
2889 int i;
2890 rtx addr = expand_normal (address);
2891 rtx mem = gen_rtx_MEM (BLKmode, addr);
2893 /* This needs to match msp430_unwind_word_mode (above). */
2894 if (!msp430x)
2895 return;
2897 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2899 unsigned int dnum = DWARF_FRAME_REGNUM (i);
2900 unsigned int rnum = DWARF2_FRAME_REG_OUT (dnum, 1);
2902 if (rnum < DWARF_FRAME_REGISTERS)
2904 HOST_WIDE_INT offset = rnum * GET_MODE_SIZE (QImode);
2906 emit_move_insn (adjust_address (mem, QImode, offset),
2907 gen_int_mode (4, QImode));
2912 /* This is a list of MD patterns that implement fixed-count shifts. */
2913 static struct
2915 const char *name;
2916 int count;
2917 int need_430x;
2918 rtx (*genfunc)(rtx,rtx);
2920 const_shift_helpers[] =
2922 #define CSH(N,C,X,G) { "__mspabi_" N, C, X, gen_##G }
2924 CSH ("slli", 1, 1, slli_1),
2925 CSH ("slll", 1, 1, slll_1),
2926 CSH ("slll", 2, 1, slll_2),
2928 CSH ("srai", 1, 0, srai_1),
2929 CSH ("sral", 1, 0, sral_1),
2930 CSH ("sral", 2, 0, sral_2),
2932 CSH ("srll", 1, 0, srll_1),
2933 CSH ("srll", 2, 1, srll_2x),
2934 { 0, 0, 0, 0 }
2935 #undef CSH
2938 /* The MSP430 ABI defines a number of helper functions that should be
2939 used for, for example, 32-bit shifts. This function is called to
2940 emit such a function, using the table above to optimize some
2941 cases. */
2942 void
2943 msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variants)
2945 rtx c, f;
2946 char *helper_const = NULL;
2947 int arg2 = 13;
2948 int arg1sz = 1;
2949 machine_mode arg0mode = GET_MODE (operands[0]);
2950 machine_mode arg1mode = GET_MODE (operands[1]);
2951 machine_mode arg2mode = GET_MODE (operands[2]);
2952 int have_430x = msp430x ? 1 : 0;
2954 if (CONST_INT_P (operands[2]))
2956 int i;
2958 for (i=0; const_shift_helpers[i].name; i++)
2960 if (const_shift_helpers[i].need_430x <= have_430x
2961 && strcmp (helper_name, const_shift_helpers[i].name) == 0
2962 && INTVAL (operands[2]) == const_shift_helpers[i].count)
2964 emit_insn (const_shift_helpers[i].genfunc (operands[0], operands[1]));
2965 return;
2970 if (arg1mode == VOIDmode)
2971 arg1mode = arg0mode;
2972 if (arg2mode == VOIDmode)
2973 arg2mode = arg0mode;
2975 if (arg1mode == SImode)
2977 arg2 = 14;
2978 arg1sz = 2;
2981 if (const_variants
2982 && CONST_INT_P (operands[2])
2983 && INTVAL (operands[2]) >= 1
2984 && INTVAL (operands[2]) <= 15)
2986 /* Note that the INTVAL is limited in value and length by the conditional above. */
2987 int len = strlen (helper_name) + 4;
2988 helper_const = (char *) xmalloc (len);
2989 snprintf (helper_const, len, "%s_%d", helper_name, (int) INTVAL (operands[2]));
2992 emit_move_insn (gen_rtx_REG (arg1mode, 12),
2993 operands[1]);
2994 if (!helper_const)
2995 emit_move_insn (gen_rtx_REG (arg2mode, arg2),
2996 operands[2]);
2998 c = gen_call_value_internal (gen_rtx_REG (arg0mode, 12),
2999 gen_rtx_SYMBOL_REF (VOIDmode, helper_const ? helper_const : helper_name),
3000 GEN_INT (0));
3001 c = emit_call_insn (c);
3002 RTL_CONST_CALL_P (c) = 1;
3004 f = 0;
3005 use_regs (&f, 12, arg1sz);
3006 if (!helper_const)
3007 use_regs (&f, arg2, 1);
3008 add_function_usage_to (c, f);
3010 emit_move_insn (operands[0],
3011 gen_rtx_REG (arg0mode, 12));
3014 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
3015 void
3016 msp430_fixup_compare_operands (machine_mode my_mode, rtx * operands)
3018 /* constants we're looking for, not constants which are allowed. */
3019 int const_op_idx = 1;
3021 if (msp430_reversible_cmp_operator (operands[0], VOIDmode))
3022 const_op_idx = 2;
3024 if (GET_CODE (operands[const_op_idx]) != REG
3025 && GET_CODE (operands[const_op_idx]) != MEM)
3026 operands[const_op_idx] = copy_to_mode_reg (my_mode, operands[const_op_idx]);
3029 /* Simplify_gen_subreg() doesn't handle memory references the way we
3030 need it to below, so we use this function for when we must get a
3031 valid subreg in a "natural" state. */
3033 msp430_subreg (machine_mode mode, rtx r, machine_mode omode, int byte)
3035 rtx rv;
3037 if (GET_CODE (r) == SUBREG
3038 && SUBREG_BYTE (r) == 0)
3040 rtx ireg = SUBREG_REG (r);
3041 machine_mode imode = GET_MODE (ireg);
3043 /* special case for (HI (SI (PSI ...), 0)) */
3044 if (imode == PSImode
3045 && mode == HImode
3046 && byte == 0)
3047 rv = gen_rtx_SUBREG (mode, ireg, byte);
3048 else
3049 rv = simplify_gen_subreg (mode, ireg, imode, byte);
3051 else if (GET_CODE (r) == MEM)
3052 rv = adjust_address (r, mode, byte);
3053 else if (GET_CODE (r) == SYMBOL_REF
3054 && (byte == 0 || byte == 2)
3055 && mode == HImode)
3057 rv = gen_rtx_ZERO_EXTRACT (HImode, r, GEN_INT (16), GEN_INT (8*byte));
3058 rv = gen_rtx_CONST (HImode, r);
3060 else
3061 rv = simplify_gen_subreg (mode, r, omode, byte);
3063 if (!rv)
3064 gcc_unreachable ();
3066 return rv;
3069 /* Called by movsi_x to generate the HImode operands. */
3070 void
3071 msp430_split_movsi (rtx *operands)
3073 rtx op00, op02, op10, op12;
3075 op00 = msp430_subreg (HImode, operands[0], SImode, 0);
3076 op02 = msp430_subreg (HImode, operands[0], SImode, 2);
3078 if (GET_CODE (operands[1]) == CONST
3079 || GET_CODE (operands[1]) == SYMBOL_REF)
3081 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
3082 op10 = gen_rtx_CONST (HImode, op10);
3083 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
3084 op12 = gen_rtx_CONST (HImode, op12);
3086 else
3088 op10 = msp430_subreg (HImode, operands[1], SImode, 0);
3089 op12 = msp430_subreg (HImode, operands[1], SImode, 2);
3092 if (rtx_equal_p (operands[0], operands[1]))
3094 operands[2] = op02;
3095 operands[4] = op12;
3096 operands[3] = op00;
3097 operands[5] = op10;
3099 else if (rtx_equal_p (op00, op12)
3100 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
3101 || (REG_P (op00) && reg_mentioned_p (op00, op10))
3102 /* Or storing (rN) into mem (rN). */
3103 || (REG_P (op10) && reg_mentioned_p (op10, op00))
3106 operands[2] = op02;
3107 operands[4] = op12;
3108 operands[3] = op00;
3109 operands[5] = op10;
3111 else
3113 operands[2] = op00;
3114 operands[4] = op10;
3115 operands[3] = op02;
3116 operands[5] = op12;
3121 /* The MSPABI specifies the names of various helper functions, many of
3122 which are compatible with GCC's helpers. This table maps the GCC
3123 name to the MSPABI name. */
3124 static const struct
3126 char const * const gcc_name;
3127 char const * const ti_name;
3129 helper_function_name_mappings [] =
3131 /* Floating point to/from integer conversions. */
3132 { "__truncdfsf2", "__mspabi_cvtdf" },
3133 { "__extendsfdf2", "__mspabi_cvtfd" },
3134 { "__fixdfhi", "__mspabi_fixdi" },
3135 { "__fixdfsi", "__mspabi_fixdli" },
3136 { "__fixdfdi", "__mspabi_fixdlli" },
3137 { "__fixunsdfhi", "__mspabi_fixdu" },
3138 { "__fixunsdfsi", "__mspabi_fixdul" },
3139 { "__fixunsdfdi", "__mspabi_fixdull" },
3140 { "__fixsfhi", "__mspabi_fixfi" },
3141 { "__fixsfsi", "__mspabi_fixfli" },
3142 { "__fixsfdi", "__mspabi_fixflli" },
3143 { "__fixunsfhi", "__mspabi_fixfu" },
3144 { "__fixunsfsi", "__mspabi_fixful" },
3145 { "__fixunsfdi", "__mspabi_fixfull" },
3146 { "__floathisf", "__mspabi_fltif" },
3147 { "__floatsisf", "__mspabi_fltlif" },
3148 { "__floatdisf", "__mspabi_fltllif" },
3149 { "__floathidf", "__mspabi_fltid" },
3150 { "__floatsidf", "__mspabi_fltlid" },
3151 { "__floatdidf", "__mspabi_fltllid" },
3152 { "__floatunhisf", "__mspabi_fltuf" },
3153 { "__floatunsisf", "__mspabi_fltulf" },
3154 { "__floatundisf", "__mspabi_fltullf" },
3155 { "__floatunhidf", "__mspabi_fltud" },
3156 { "__floatunsidf", "__mspabi_fltuld" },
3157 { "__floatundidf", "__mspabi_fltulld" },
3159 /* Floating point comparisons. */
3160 /* GCC uses individual functions for each comparison, TI uses one
3161 compare <=> function. */
3163 /* Floating point arithmatic */
3164 { "__adddf3", "__mspabi_addd" },
3165 { "__addsf3", "__mspabi_addf" },
3166 { "__divdf3", "__mspabi_divd" },
3167 { "__divsf3", "__mspabi_divf" },
3168 { "__muldf3", "__mspabi_mpyd" },
3169 { "__mulsf3", "__mspabi_mpyf" },
3170 { "__subdf3", "__mspabi_subd" },
3171 { "__subsf3", "__mspabi_subf" },
3172 /* GCC does not use helper functions for negation */
3174 /* Integer multiply, divide, remainder. */
3175 { "__mulhi3", "__mspabi_mpyi" },
3176 { "__mulsi3", "__mspabi_mpyl" },
3177 { "__muldi3", "__mspabi_mpyll" },
3178 #if 0
3179 /* Clarify signed vs unsigned first. */
3180 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
3181 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
3182 #endif
3184 { "__divhi3", "__mspabi_divi" },
3185 { "__divsi3", "__mspabi_divli" },
3186 { "__divdi3", "__mspabi_divlli" },
3187 { "__udivhi3", "__mspabi_divu" },
3188 { "__udivsi3", "__mspabi_divul" },
3189 { "__udivdi3", "__mspabi_divull" },
3190 { "__modhi3", "__mspabi_remi" },
3191 { "__modsi3", "__mspabi_remli" },
3192 { "__moddi3", "__mspabi_remlli" },
3193 { "__umodhi3", "__mspabi_remu" },
3194 { "__umodsi3", "__mspabi_remul" },
3195 { "__umoddi3", "__mspabi_remull" },
3197 /* Bitwise operations. */
3198 /* Rotation - no rotation support yet. */
3199 /* Logical left shift - gcc already does these itself. */
3200 /* Arithmetic left shift - gcc already does these itself. */
3201 /* Arithmetic right shift - gcc already does these itself. */
3203 { NULL, NULL }
3206 /* Returns true if the current MCU supports an F5xxx series
3207 hardware multiper. */
3209 bool
3210 msp430_use_f5_series_hwmult (void)
3212 static const char * cached_match = NULL;
3213 static bool cached_result;
3215 if (msp430_hwmult_type == MSP430_HWMULT_F5SERIES)
3216 return true;
3218 if (target_mcu == NULL || msp430_hwmult_type != MSP430_HWMULT_AUTO)
3219 return false;
3221 if (target_mcu == cached_match)
3222 return cached_result;
3224 cached_match = target_mcu;
3226 if (strncasecmp (target_mcu, "msp430f5", 8) == 0)
3227 return cached_result = true;
3228 if (strncasecmp (target_mcu, "msp430fr5", 9) == 0)
3229 return cached_result = true;
3230 if (strncasecmp (target_mcu, "msp430f6", 8) == 0)
3231 return cached_result = true;
3233 int i;
3235 /* FIXME: This array is alpha sorted - we could use a binary search. */
3236 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
3237 if (strcasecmp (target_mcu, msp430_mcu_data[i].name) == 0)
3238 return cached_result = msp430_mcu_data[i].hwmpy == 8;
3240 return cached_result = false;
3243 /* Returns true if the current MCU has a second generation
3244 32-bit hardware multiplier. */
3246 static bool
3247 use_32bit_hwmult (void)
3249 static const char * cached_match = NULL;
3250 static bool cached_result;
3251 int i;
3253 if (msp430_hwmult_type == MSP430_HWMULT_LARGE)
3254 return true;
3256 if (target_mcu == NULL || msp430_hwmult_type != MSP430_HWMULT_AUTO)
3257 return false;
3259 if (target_mcu == cached_match)
3260 return cached_result;
3262 cached_match = target_mcu;
3264 /* FIXME: This array is alpha sorted - we could use a binary search. */
3265 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
3266 if (strcasecmp (target_mcu, msp430_mcu_data[i].name) == 0)
3267 return cached_result = msp430_mcu_data[i].hwmpy == 4;
3269 return cached_result = false;
3272 /* Returns true if the current MCU does not have a
3273 hardware multiplier of any kind. */
3275 static bool
3276 msp430_no_hwmult (void)
3278 static const char * cached_match = NULL;
3279 static bool cached_result;
3280 int i;
3282 if (msp430_hwmult_type == MSP430_HWMULT_NONE)
3283 return true;
3285 if (msp430_hwmult_type != MSP430_HWMULT_AUTO)
3286 return false;
3288 if (target_mcu == NULL)
3289 return true;
3291 if (target_mcu == cached_match)
3292 return cached_result;
3294 cached_match = target_mcu;
3296 /* FIXME: This array is alpha sorted - we could use a binary search. */
3297 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
3298 if (strcasecmp (target_mcu, msp430_mcu_data[i].name) == 0)
3299 return cached_result = msp430_mcu_data[i].hwmpy == 0;
3301 /* If we do not recognise the MCU name, we assume that it does not support
3302 any kind of hardware multiply - this is the safest assumption to make. */
3303 return cached_result = true;
3306 /* This function does the same as the default, but it will replace GCC
3307 function names with the MSPABI-specified ones. */
3309 void
3310 msp430_output_labelref (FILE *file, const char *name)
3312 int i;
3314 for (i = 0; helper_function_name_mappings [i].gcc_name; i++)
3315 if (strcmp (helper_function_name_mappings [i].gcc_name, name) == 0)
3317 name = helper_function_name_mappings [i].ti_name;
3318 break;
3321 /* If we have been given a specific MCU name then we may be
3322 able to make use of its hardware multiply capabilities. */
3323 if (msp430_hwmult_type != MSP430_HWMULT_NONE)
3325 if (strcmp ("__mspabi_mpyi", name) == 0)
3327 if (msp430_use_f5_series_hwmult ())
3328 name = "__mulhi2_f5";
3329 else if (! msp430_no_hwmult ())
3330 name = "__mulhi2";
3332 else if (strcmp ("__mspabi_mpyl", name) == 0)
3334 if (msp430_use_f5_series_hwmult ())
3335 name = "__mulsi2_f5";
3336 else if (use_32bit_hwmult ())
3337 name = "__mulsi2_hw32";
3338 else if (! msp430_no_hwmult ())
3339 name = "__mulsi2";
3343 fputs (name, file);
3346 /* Common code for msp430_print_operand... */
3348 static void
3349 msp430_print_operand_raw (FILE * file, rtx op)
3351 HOST_WIDE_INT i;
3353 switch (GET_CODE (op))
3355 case REG:
3356 fprintf (file, "%s", reg_names [REGNO (op)]);
3357 break;
3359 case CONST_INT:
3360 i = INTVAL (op);
3361 if (TARGET_ASM_HEX)
3362 fprintf (file, "%#" HOST_WIDE_INT_PRINT "x", i);
3363 else
3364 fprintf (file, "%" HOST_WIDE_INT_PRINT "d", i);
3365 break;
3367 case CONST:
3368 case PLUS:
3369 case MINUS:
3370 case SYMBOL_REF:
3371 case LABEL_REF:
3372 output_addr_const (file, op);
3373 break;
3375 default:
3376 print_rtl (file, op);
3377 break;
3381 #undef TARGET_PRINT_OPERAND_ADDRESS
3382 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
3384 /* Output to stdio stream FILE the assembler syntax for an
3385 instruction operand that is a memory reference whose address
3386 is ADDR. */
3388 static void
3389 msp430_print_operand_addr (FILE * file, machine_mode /*mode*/, rtx addr)
3391 switch (GET_CODE (addr))
3393 case PLUS:
3394 msp430_print_operand_raw (file, XEXP (addr, 1));
3395 gcc_assert (REG_P (XEXP (addr, 0)));
3396 fprintf (file, "(%s)", reg_names [REGNO (XEXP (addr, 0))]);
3397 return;
3399 case REG:
3400 fprintf (file, "@");
3401 break;
3403 case CONST:
3404 case CONST_INT:
3405 case SYMBOL_REF:
3406 case LABEL_REF:
3407 fprintf (file, "&");
3408 break;
3410 default:
3411 break;
3414 msp430_print_operand_raw (file, addr);
3417 #undef TARGET_PRINT_OPERAND
3418 #define TARGET_PRINT_OPERAND msp430_print_operand
3420 /* A low 16-bits of int/lower of register pair
3421 B high 16-bits of int/higher of register pair
3422 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
3423 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
3424 H like %B (for backwards compatibility)
3425 I inverse of value
3426 J an integer without a # prefix
3427 L like %A (for backwards compatibility)
3428 O offset of the top of the stack
3429 Q like X but generates an A postfix
3430 R inverse of condition code, unsigned.
3431 X X instruction postfix in large mode
3432 Y value - 4
3433 Z value - 1
3434 b .B or .W or .A, depending upon the mode
3435 p bit position
3436 r inverse of condition code
3437 x like X but only for pointers. */
3439 static void
3440 msp430_print_operand (FILE * file, rtx op, int letter)
3442 rtx addr;
3444 /* We can't use c, n, a, or l. */
3445 switch (letter)
3447 case 'Z':
3448 gcc_assert (CONST_INT_P (op));
3449 /* Print the constant value, less one. */
3450 fprintf (file, "#%ld", INTVAL (op) - 1);
3451 return;
3452 case 'Y':
3453 gcc_assert (CONST_INT_P (op));
3454 /* Print the constant value, less four. */
3455 fprintf (file, "#%ld", INTVAL (op) - 4);
3456 return;
3457 case 'I':
3458 if (GET_CODE (op) == CONST_INT)
3460 /* Inverse of constants */
3461 int i = INTVAL (op);
3462 fprintf (file, "%d", ~i);
3463 return;
3465 op = XEXP (op, 0);
3466 break;
3467 case 'r': /* Conditional jump where the condition is reversed. */
3468 switch (GET_CODE (op))
3470 case EQ: fprintf (file, "NE"); break;
3471 case NE: fprintf (file, "EQ"); break;
3472 case GEU: fprintf (file, "LO"); break;
3473 case LTU: fprintf (file, "HS"); break;
3474 case GE: fprintf (file, "L"); break;
3475 case LT: fprintf (file, "GE"); break;
3476 /* Assume these have reversed operands. */
3477 case GTU: fprintf (file, "HS"); break;
3478 case LEU: fprintf (file, "LO"); break;
3479 case GT: fprintf (file, "GE"); break;
3480 case LE: fprintf (file, "L"); break;
3481 default:
3482 msp430_print_operand_raw (file, op);
3483 break;
3485 return;
3486 case 'R': /* Conditional jump where the operands are reversed. */
3487 switch (GET_CODE (op))
3489 case GTU: fprintf (file, "LO"); break;
3490 case LEU: fprintf (file, "HS"); break;
3491 case GT: fprintf (file, "L"); break;
3492 case LE: fprintf (file, "GE"); break;
3493 default:
3494 msp430_print_operand_raw (file, op);
3495 break;
3497 return;
3498 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
3499 gcc_assert (CONST_INT_P (op));
3500 fprintf (file, "#%d", 1 << INTVAL (op));
3501 return;
3502 case 'b':
3503 switch (GET_MODE (op))
3505 case QImode: fprintf (file, ".B"); return;
3506 case HImode: fprintf (file, ".W"); return;
3507 case PSImode: fprintf (file, ".A"); return;
3508 case SImode: fprintf (file, ".A"); return;
3509 default:
3510 return;
3512 case 'A':
3513 case 'L': /* Low half. */
3514 switch (GET_CODE (op))
3516 case MEM:
3517 op = adjust_address (op, Pmode, 0);
3518 break;
3519 case REG:
3520 break;
3521 case CONST_INT:
3522 op = GEN_INT (INTVAL (op) & 0xffff);
3523 letter = 0;
3524 break;
3525 default:
3526 /* If you get here, figure out a test case :-) */
3527 gcc_unreachable ();
3529 break;
3530 case 'B':
3531 case 'H': /* high half */
3532 switch (GET_CODE (op))
3534 case MEM:
3535 op = adjust_address (op, Pmode, 2);
3536 break;
3537 case REG:
3538 op = gen_rtx_REG (Pmode, REGNO (op) + 1);
3539 break;
3540 case CONST_INT:
3541 op = GEN_INT (INTVAL (op) >> 16);
3542 letter = 0;
3543 break;
3544 default:
3545 /* If you get here, figure out a test case :-) */
3546 gcc_unreachable ();
3548 break;
3549 case 'C':
3550 switch (GET_CODE (op))
3552 case MEM:
3553 op = adjust_address (op, Pmode, 3);
3554 break;
3555 case REG:
3556 op = gen_rtx_REG (Pmode, REGNO (op) + 2);
3557 break;
3558 case CONST_INT:
3559 op = GEN_INT ((long long) INTVAL (op) >> 32);
3560 letter = 0;
3561 break;
3562 default:
3563 /* If you get here, figure out a test case :-) */
3564 gcc_unreachable ();
3566 break;
3567 case 'D':
3568 switch (GET_CODE (op))
3570 case MEM:
3571 op = adjust_address (op, Pmode, 4);
3572 break;
3573 case REG:
3574 op = gen_rtx_REG (Pmode, REGNO (op) + 3);
3575 break;
3576 case CONST_INT:
3577 op = GEN_INT ((long long) INTVAL (op) >> 48);
3578 letter = 0;
3579 break;
3580 default:
3581 /* If you get here, figure out a test case :-) */
3582 gcc_unreachable ();
3584 break;
3586 case 'X':
3587 /* This is used to turn, for example, an ADD opcode into an ADDX
3588 opcode when we're using 20-bit addresses. */
3589 if (TARGET_LARGE || GET_MODE (op) == PSImode)
3590 fprintf (file, "X");
3591 /* We don't care which operand we use, but we want 'X' in the MD
3592 file, so we do it this way. */
3593 return;
3595 case 'x':
3596 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
3597 if (GET_MODE (op) == PSImode)
3598 fprintf (file, "X");
3599 return;
3601 case 'Q':
3602 /* Likewise, for BR -> BRA. */
3603 if (TARGET_LARGE)
3604 fprintf (file, "A");
3605 return;
3607 case 'O':
3608 /* Computes the offset to the top of the stack for the current frame.
3609 This has to be done here rather than in, say, msp430_expand_builtin()
3610 because builtins are expanded before the frame layout is determined. */
3611 fprintf (file, "%d",
3612 msp430_initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM)
3613 - (TARGET_LARGE ? 4 : 2));
3614 return;
3616 case 'J':
3617 gcc_assert (GET_CODE (op) == CONST_INT);
3618 case 0:
3619 break;
3620 default:
3621 output_operand_lossage ("invalid operand prefix");
3622 return;
3625 switch (GET_CODE (op))
3627 case REG:
3628 msp430_print_operand_raw (file, op);
3629 break;
3631 case MEM:
3632 addr = XEXP (op, 0);
3633 msp430_print_operand_addr (file, GET_MODE (op), addr);
3634 break;
3636 case CONST:
3637 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTRACT)
3639 op = XEXP (op, 0);
3640 switch (INTVAL (XEXP (op, 2)))
3642 case 0:
3643 fprintf (file, "#lo (");
3644 msp430_print_operand_raw (file, XEXP (op, 0));
3645 fprintf (file, ")");
3646 break;
3648 case 16:
3649 fprintf (file, "#hi (");
3650 msp430_print_operand_raw (file, XEXP (op, 0));
3651 fprintf (file, ")");
3652 break;
3654 default:
3655 output_operand_lossage ("invalid zero extract");
3656 break;
3658 break;
3660 /* Fall through. */
3661 case CONST_INT:
3662 case SYMBOL_REF:
3663 case LABEL_REF:
3664 if (letter == 0)
3665 fprintf (file, "#");
3666 msp430_print_operand_raw (file, op);
3667 break;
3669 case EQ: fprintf (file, "EQ"); break;
3670 case NE: fprintf (file, "NE"); break;
3671 case GEU: fprintf (file, "HS"); break;
3672 case LTU: fprintf (file, "LO"); break;
3673 case GE: fprintf (file, "GE"); break;
3674 case LT: fprintf (file, "L"); break;
3676 default:
3677 print_rtl (file, op);
3678 break;
3683 /* Frame stuff. */
3686 msp430_return_addr_rtx (int count)
3688 int ra_size;
3689 if (count)
3690 return NULL_RTX;
3692 ra_size = TARGET_LARGE ? 4 : 2;
3693 if (crtl->args.pretend_args_size)
3694 ra_size += 2;
3696 return gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, arg_pointer_rtx, GEN_INT (- ra_size)));
3700 msp430_incoming_return_addr_rtx (void)
3702 return gen_rtx_MEM (Pmode, stack_pointer_rtx);
3705 /* Instruction generation stuff. */
3707 /* Generate a sequence of instructions to sign-extend an HI
3708 value into an SI value. Handles the tricky case where
3709 we are overwriting the destination. */
3711 const char *
3712 msp430x_extendhisi (rtx * operands)
3714 if (REGNO (operands[0]) == REGNO (operands[1]))
3715 /* Low word of dest == source word. */
3716 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
3718 if (! msp430x)
3719 /* Note: This sequence is approximately the same length as invoking a helper
3720 function to perform the sign-extension, as in:
3722 MOV.W %1, %L0
3723 MOV.W %1, r12
3724 CALL __mspabi_srai_15
3725 MOV.W r12, %H0
3727 but this version does not involve any function calls or using argument
3728 registers, so it reduces register pressure. */
3729 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
3731 if (REGNO (operands[0]) + 1 == REGNO (operands[1]))
3732 /* High word of dest == source word. */
3733 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
3735 /* No overlap between dest and source. */
3736 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
3739 /* Likewise for logical right shifts. */
3740 const char *
3741 msp430x_logical_shift_right (rtx amount)
3743 /* The MSP430X's logical right shift instruction - RRUM - does
3744 not use an extension word, so we cannot encode a repeat count.
3745 Try various alternatives to work around this. If the count
3746 is in a register we are stuck, hence the assert. */
3747 gcc_assert (CONST_INT_P (amount));
3749 if (INTVAL (amount) <= 0
3750 || INTVAL (amount) >= 16)
3751 return "# nop logical shift.";
3753 if (INTVAL (amount) > 0
3754 && INTVAL (amount) < 5)
3755 return "rrum.w\t%2, %0"; /* Two bytes. */
3757 if (INTVAL (amount) > 4
3758 && INTVAL (amount) < 9)
3759 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
3761 /* First we logically shift right by one. Now we know
3762 that the top bit is zero and we can use the arithmetic
3763 right shift instruction to perform the rest of the shift. */
3764 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
3767 struct gcc_target targetm = TARGET_INITIALIZER;
3769 #include "gt-msp430.h"