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