comparison gcc/config/msp430/msp430.c @ 111:04ced10e8804

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