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