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