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