]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/msp430/msp430.c
[62/77] Big machine_mode to scalar_int_mode replacement
[thirdparty/gcc.git] / gcc / config / msp430 / msp430.c
CommitLineData
f6a83b4a 1/* Subroutines used for code generation on TI MSP430 processors.
cbe34bb5 2 Copyright (C) 2012-2017 Free Software Foundation, Inc.
f6a83b4a
DD
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"
c7131fb2 24#include "backend.h"
e11c4407 25#include "target.h"
c7131fb2 26#include "rtl.h"
e11c4407 27#include "tree.h"
314e6352
ML
28#include "stringpool.h"
29#include "attribs.h"
e11c4407 30#include "gimple-expr.h"
c7131fb2 31#include "df.h"
4d0cdd0c 32#include "memmodel.h"
e11c4407
AM
33#include "tm_p.h"
34#include "regs.h"
35#include "emit-rtl.h"
36#include "diagnostic-core.h"
40e23961 37#include "fold-const.h"
d8a2d370
DN
38#include "stor-layout.h"
39#include "calls.h"
f6a83b4a 40#include "output.h"
36566b39 41#include "explow.h"
f6a83b4a 42#include "expr.h"
f6a83b4a 43#include "langhooks.h"
9b2b7279 44#include "builtins.h"
61f5d852 45#include "intl.h"
d58627a0 46
994c5d85 47/* This file should be included last. */
d58627a0 48#include "target-def.h"
f6a83b4a
DD
49\f
50
51static void msp430_compute_frame_info (void);
52
53\f
54
c6f709ec 55/* Run-time Target Specification. */
f6a83b4a 56
c6f709ec 57bool msp430x = true;
f6a83b4a
DD
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
766090c2 88 m = ggc_cleared_alloc<machine_function> ();
f6a83b4a
DD
89
90 return m;
91}
92
f6a83b4a
DD
93#undef TARGET_OPTION_OVERRIDE
94#define TARGET_OPTION_OVERRIDE msp430_option_override
95
aad11912 96/* This is a copy of the same data structure found in gas/config/tc-msp430.c
01c93899 97 Also another (sort-of) copy can be found in gcc/config/msp430/t-msp430
aad11912 98 Keep these three structures in sync.
5d582919
JS
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. */
aad11912
NC
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 },
5d582919
JS
526 { "msp430fr2110",2,0 },
527 { "msp430fr2111",2,0 },
01c93899
NC
528 { "msp430fr2310",2,0 },
529 { "msp430fr2311",2,0 },
aad11912 530 { "msp430fr2433",2,8 },
01c93899
NC
531 { "msp430fr2532",2,8 },
532 { "msp430fr2533",2,8 },
533 { "msp430fr2632",2,8 },
534 { "msp430fr2633",2,8 },
aad11912
NC
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 },
01c93899
NC
587 { "msp430fr5962",2,8 },
588 { "msp430fr5964",2,8 },
aad11912
NC
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 },
01c93899
NC
601 { "msp430fr5992",2,8 },
602 { "msp430fr5994",2,8 },
5d582919 603 { "msp430fr59941",2,8 },
aad11912
NC
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};
50cfbf99
NC
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{
d4f283a1 723 if (target_mcu)
50cfbf99
NC
724 {
725 unsigned int i;
726 static char mcu_name [64];
727
d4f283a1 728 snprintf (mcu_name, sizeof (mcu_name) - 1, "__%s__", target_mcu);
50cfbf99
NC
729 for (i = strlen (mcu_name); i--;)
730 mcu_name[i] = TOUPPER (mcu_name[i]);
731 return mcu_name;
732 }
a005b5be 733
50cfbf99
NC
734 return msp430x ? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
735}
736
04a9ae28
NC
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
f6a83b4a
DD
751static void
752msp430_option_override (void)
753{
754 init_machine_status = msp430_init_machine_status;
755
4494fbc9 756 if (target_cpu)
d4f283a1 757 {
04a9ae28
NC
758 /* gcc/common/config/msp430-common.c will have
759 already canonicalised the string in target_cpu. */
f7961364 760 if (strcasecmp (target_cpu, "msp430x") == 0)
d4f283a1 761 msp430x = true;
f7961364 762 else /* target_cpu == "msp430" - already handled by the front end. */
c6f709ec 763 msp430x = false;
d4f283a1 764 }
04a9ae28
NC
765
766 if (target_mcu)
4494fbc9 767 {
c6f709ec 768 int i;
4494fbc9 769
04a9ae28 770 /* FIXME: If the array were alpha sorted, we could use a binary search. */
aad11912
NC
771 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
772 if (strcasecmp (msp430_mcu_data[i].name, target_mcu) == 0)
f7961364 773 {
04a9ae28
NC
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
b07447ba
NC
783 && msp430_hwmult_type != MSP430_HWMULT_AUTO
784 && msp430_hwmult_type != MSP430_HWMULT_NONE)
04a9ae28
NC
785 warning (0, "MCU '%s' does not have hardware multiply support, but -mhwmult is set to %s",
786 target_mcu,
b07447ba
NC
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
04a9ae28
NC
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));
b07447ba 794 else if (msp430_hwmult_type == MSP430_HWMULT_LARGE && msp430_mcu_data[i].hwmpy != 4)
04a9ae28
NC
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));
b07447ba 797 else if (msp430_hwmult_type == MSP430_HWMULT_F5SERIES && msp430_mcu_data[i].hwmpy != 8)
04a9ae28
NC
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;
f7961364
NC
803 break;
804 }
04a9ae28 805
aad11912
NC
806 if (i < 0)
807 {
b07447ba 808 if (msp430_hwmult_type == MSP430_HWMULT_AUTO)
04a9ae28
NC
809 {
810 if (msp430_warn_mcu)
811 {
812 if (target_cpu == NULL)
813 warning (0,
bd2c6270
JJ
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.",
04a9ae28
NC
818 target_mcu);
819 else
820 warning (0,
bd2c6270
JJ
821 "Unrecognized MCU name '%s', assuming that it "
822 "has no hardware multiply.\nUse the -mhwmult "
823 "option to set this explicitly.",
04a9ae28
NC
824 target_mcu);
825 }
826
b07447ba 827 msp430_hwmult_type = MSP430_HWMULT_NONE;
04a9ae28
NC
828 }
829 else if (target_cpu == NULL)
830 {
831 if (msp430_warn_mcu)
832 warning (0,
bd2c6270
JJ
833 "Unrecognized MCU name '%s', assuming that it just "
834 "supports the MSP430 ISA.\nUse the -mcpu option to "
835 "set the ISA explicitly.",
04a9ae28
NC
836 target_mcu);
837
838 msp430x = false;
839 }
840 else if (msp430_warn_mcu)
bd2c6270 841 warning (0, "Unrecognized MCU name '%s'.", target_mcu);
aad11912 842 }
4494fbc9 843 }
f6a83b4a 844
04a9ae28 845 /* The F5 series are all able to support the 430X ISA. */
b07447ba 846 if (target_cpu == NULL && target_mcu == NULL && msp430_hwmult_type == MSP430_HWMULT_F5SERIES)
04a9ae28
NC
847 msp430x = true;
848
f6a83b4a 849 if (TARGET_LARGE && !msp430x)
cad055a4 850 error ("-mlarge requires a 430X-compatible -mmcu=");
f6a83b4a 851
b07447ba 852 if (msp430_code_region == MSP430_REGION_UPPER && ! msp430x)
d7edde11 853 error ("-mcode-region=upper requires 430X-compatible cpu");
b07447ba 854 if (msp430_data_region == MSP430_REGION_UPPER && ! msp430x)
d7edde11
NC
855 error ("-mdata-region=upper requires 430X-compatible cpu");
856
f6a83b4a
DD
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
c32ab325
DD
871#undef TARGET_SCALAR_MODE_SUPPORTED_P
872#define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
873
874static bool
ef4bddc2 875msp430_scalar_mode_supported_p (machine_mode m)
c32ab325
DD
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
f6a83b4a
DD
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
903/* Implements HARD_REGNO_NREGS. MSP430X registers can hold a single
904 PSImode value, but not an SImode value. */
905int
906msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED,
ef4bddc2 907 machine_mode mode)
f6a83b4a
DD
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
c32ab325
DD
915/* Implements HARD_REGNO_NREGS_HAS_PADDING. */
916int
917msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED,
ef4bddc2 918 machine_mode mode)
c32ab325
DD
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,
ef4bddc2 929 machine_mode mode)
c32ab325
DD
930{
931 if (mode == PSImode)
932 return 2;
933 return msp430_hard_regno_nregs (regno, mode);
934}
935
f6a83b4a
DD
936/* Implements HARD_REGNO_MODE_OK. */
937int
938msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED,
ef4bddc2 939 machine_mode mode)
f6a83b4a
DD
940{
941 return regno <= (ARG_POINTER_REGNUM - msp430_hard_regno_nregs (regno, mode));
942}
943
944/* Implements MODES_TIEABLE_P. */
945bool
ef4bddc2 946msp430_modes_tieable_p (machine_mode mode1, machine_mode mode2)
f6a83b4a
DD
947{
948 if ((mode1 == PSImode || mode2 == SImode)
949 || (mode1 == SImode || mode2 == PSImode))
950 return false;
951
952 return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
953 || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
954 == (GET_MODE_CLASS (mode2) == MODE_FLOAT
955 || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
956}
957
958#undef TARGET_FRAME_POINTER_REQUIRED
959#define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
960
961static bool
962msp430_frame_pointer_required (void)
963{
964 return false;
965}
966
967#undef TARGET_CAN_ELIMINATE
968#define TARGET_CAN_ELIMINATE msp430_can_eliminate
969
970static bool
971msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED,
972 const int to_reg ATTRIBUTE_UNUSED)
973{
974 return true;
975}
976
977/* Implements INITIAL_ELIMINATION_OFFSET. */
978int
cad055a4 979msp430_initial_elimination_offset (int from, int to)
f6a83b4a 980{
cad055a4 981 int rv = 0; /* As if arg to arg. */
f6a83b4a
DD
982
983 msp430_compute_frame_info ();
984
985 switch (to)
986 {
987 case STACK_POINTER_REGNUM:
988 rv += cfun->machine->framesize_outgoing;
989 rv += cfun->machine->framesize_locals;
990 /* Fall through. */
991 case FRAME_POINTER_REGNUM:
992 rv += cfun->machine->framesize_regs;
993 /* Allow for the saved return address. */
994 rv += (TARGET_LARGE ? 4 : 2);
995 /* NB/ No need to allow for crtl->args.pretend_args_size.
996 GCC does that for us. */
997 break;
998 default:
999 gcc_unreachable ();
1000 }
1001
1002 switch (from)
1003 {
1004 case FRAME_POINTER_REGNUM:
1005 /* Allow for the fall through above. */
1006 rv -= (TARGET_LARGE ? 4 : 2);
1007 rv -= cfun->machine->framesize_regs;
1008 case ARG_POINTER_REGNUM:
1009 break;
1010 default:
1011 gcc_unreachable ();
1012 }
1013
1014 return rv;
1015}
1016\f
1017/* Named Address Space support */
1018
1019
1020/* Return the appropriate mode for a named address pointer. */
1021#undef TARGET_ADDR_SPACE_POINTER_MODE
1022#define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
1023#undef TARGET_ADDR_SPACE_ADDRESS_MODE
1024#define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
1025
095a2d76 1026static scalar_int_mode
f6a83b4a
DD
1027msp430_addr_space_pointer_mode (addr_space_t addrspace)
1028{
1029 switch (addrspace)
1030 {
1031 default:
1032 case ADDR_SPACE_GENERIC:
1033 return Pmode;
1034 case ADDR_SPACE_NEAR:
1035 return HImode;
1036 case ADDR_SPACE_FAR:
1037 return PSImode;
1038 }
1039}
1040
1041/* Function pointers are stored in unwind_word sized
1042 variables, so make sure that unwind_word is big enough. */
1043#undef TARGET_UNWIND_WORD_MODE
1044#define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
1045
095a2d76 1046static scalar_int_mode
f6a83b4a
DD
1047msp430_unwind_word_mode (void)
1048{
04a9ae28
NC
1049 /* This needs to match msp430_init_dwarf_reg_sizes_extra (below). */
1050 return msp430x ? PSImode : HImode;
f6a83b4a
DD
1051}
1052
1053/* Determine if one named address space is a subset of another. */
1054#undef TARGET_ADDR_SPACE_SUBSET_P
1055#define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
1056static bool
1057msp430_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
1058{
1059 if (subset == superset)
1060 return true;
1061 else
1062 return (subset != ADDR_SPACE_FAR && superset == ADDR_SPACE_FAR);
1063}
1064
1065#undef TARGET_ADDR_SPACE_CONVERT
1066#define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
1067/* Convert from one address space to another. */
1068static rtx
1069msp430_addr_space_convert (rtx op, tree from_type, tree to_type)
1070{
1071 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
1072 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
1073 rtx result;
1074
1075 if (to_as != ADDR_SPACE_FAR && from_as == ADDR_SPACE_FAR)
1076 {
1077 /* This is unpredictable, as we're truncating off usable address
1078 bits. */
1079
1080 if (CONSTANT_P (op))
1081 return gen_rtx_CONST (HImode, op);
1082
1083 result = gen_reg_rtx (HImode);
1084 emit_insn (gen_truncpsihi2 (result, op));
1085 return result;
1086 }
1087 else if (to_as == ADDR_SPACE_FAR && from_as != ADDR_SPACE_FAR)
1088 {
1089 /* This always works. */
1090
1091 if (CONSTANT_P (op))
1092 return gen_rtx_CONST (PSImode, op);
1093
1094 result = gen_reg_rtx (PSImode);
1095 emit_insn (gen_zero_extendhipsi2 (result, op));
1096 return result;
1097 }
1098 else
1099 gcc_unreachable ();
1100}
1101\f
1102/* Stack Layout and Calling Conventions. */
1103
1104/* For each function, we list the gcc version and the TI version on
1105 each line, where we're converting the function names. */
1106static char const * const special_convention_function_names [] =
1107{
1108 "__muldi3", "__mspabi_mpyll",
1109 "__udivdi3", "__mspabi_divull",
1110 "__umoddi3", "__mspabi_remull",
1111 "__divdi3", "__mspabi_divlli",
1112 "__moddi3", "__mspabi_remlli",
1113 "__mspabi_srall",
1114 "__mspabi_srlll",
1115 "__mspabi_sllll",
1116 "__adddf3", "__mspabi_addd",
1117 "__subdf3", "__mspabi_subd",
1118 "__muldf3", "__mspabi_mpyd",
1119 "__divdf3", "__mspabi_divd",
1120 "__mspabi_cmpd",
1121 NULL
1122};
1123
1124/* TRUE if the function passed is a "speical" function. Special
1125 functions pass two DImode parameters in registers. */
1126static bool
1127msp430_special_register_convention_p (const char *name)
1128{
1129 int i;
1130
1131 for (i = 0; special_convention_function_names [i]; i++)
1132 if (! strcmp (name, special_convention_function_names [i]))
1133 return true;
1134
1135 return false;
1136}
1137
1138#undef TARGET_FUNCTION_VALUE_REGNO_P
1139#define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
1140
1141bool
1142msp430_function_value_regno_p (unsigned int regno)
1143{
1144 return regno == 12;
1145}
1146
1147
1148#undef TARGET_FUNCTION_VALUE
1149#define TARGET_FUNCTION_VALUE msp430_function_value
1150
1151rtx
1152msp430_function_value (const_tree ret_type,
1153 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1154 bool outgoing ATTRIBUTE_UNUSED)
1155{
1156 return gen_rtx_REG (TYPE_MODE (ret_type), 12);
1157}
1158
1159#undef TARGET_LIBCALL_VALUE
1160#define TARGET_LIBCALL_VALUE msp430_libcall_value
1161
1162rtx
ef4bddc2 1163msp430_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
f6a83b4a
DD
1164{
1165 return gen_rtx_REG (mode, 12);
1166}
1167
1168/* Implements INIT_CUMULATIVE_ARGS. */
1169void
1170msp430_init_cumulative_args (CUMULATIVE_ARGS *ca,
1171 tree fntype ATTRIBUTE_UNUSED,
1172 rtx libname ATTRIBUTE_UNUSED,
1173 tree fndecl ATTRIBUTE_UNUSED,
1174 int n_named_args ATTRIBUTE_UNUSED)
1175{
1176 const char *fname;
1177 memset (ca, 0, sizeof(*ca));
1178
1179 ca->can_split = 1;
1180
1181 if (fndecl)
1182 fname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
1183 else if (libname)
1184 fname = XSTR (libname, 0);
1185 else
1186 fname = NULL;
1187
1188 if (fname && msp430_special_register_convention_p (fname))
1189 ca->special_p = 1;
1190}
1191
1192/* Helper function for argument passing; this function is the common
1193 code that determines where an argument will be passed. */
1194static void
1195msp430_evaluate_arg (cumulative_args_t cap,
ef4bddc2 1196 machine_mode mode,
f6a83b4a
DD
1197 const_tree type ATTRIBUTE_UNUSED,
1198 bool named)
1199{
1200 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1201 int nregs = GET_MODE_SIZE (mode);
1202 int i;
1203
1204 ca->reg_count = 0;
1205 ca->mem_count = 0;
1206
1207 if (!named)
1208 return;
1209
1210 if (mode == PSImode)
1211 nregs = 1;
1212 else
1213 nregs = (nregs + 1) / 2;
1214
1215 if (ca->special_p)
1216 {
1217 /* Function is passed two DImode operands, in R8:R11 and
1218 R12:15. */
1219 ca->start_reg = 8;
1220 ca->reg_count = 4;
1221 return;
1222 }
1223
1224 switch (nregs)
1225 {
1226 case 1:
1227 for (i = 0; i < 4; i++)
1228 if (! ca->reg_used [i])
1229 {
1230 ca->reg_count = 1;
1231 ca->start_reg = CA_FIRST_REG + i;
1232 return;
1233 }
1234 break;
1235 case 2:
1236 for (i = 0; i < 3; i++)
1237 if (! ca->reg_used [i] && ! ca->reg_used [i + 1])
1238 {
1239 ca->reg_count = 2;
1240 ca->start_reg = CA_FIRST_REG + i;
1241 return;
1242 }
1243 if (! ca->reg_used [3] && ca->can_split)
1244 {
1245 ca->reg_count = 1;
1246 ca->mem_count = 2;
1247 ca->start_reg = CA_FIRST_REG + 3;
1248 return;
1249 }
1250 break;
1251 case 3:
1252 case 4:
1253 ca->can_split = 0;
1254 if (! ca->reg_used [0]
1255 && ! ca->reg_used [1]
1256 && ! ca->reg_used [2]
1257 && ! ca->reg_used [3])
1258 {
1259 ca->reg_count = 4;
1260 ca->start_reg = CA_FIRST_REG;
1261 return;
1262 }
1263 break;
1264 }
1265}
1266
1267#undef TARGET_PROMOTE_PROTOTYPES
1268#define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
1269
1270bool
1271msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED)
1272{
1273 return false;
1274}
1275
1276#undef TARGET_FUNCTION_ARG
1277#define TARGET_FUNCTION_ARG msp430_function_arg
1278
1279rtx
1280msp430_function_arg (cumulative_args_t cap,
ef4bddc2 1281 machine_mode mode,
f6a83b4a
DD
1282 const_tree type,
1283 bool named)
1284{
1285 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1286
1287 msp430_evaluate_arg (cap, mode, type, named);
1288
1289 if (ca->reg_count)
1290 return gen_rtx_REG (mode, ca->start_reg);
1291
1292 return 0;
1293}
1294
1295#undef TARGET_ARG_PARTIAL_BYTES
1296#define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
1297
1298int
1299msp430_arg_partial_bytes (cumulative_args_t cap,
ef4bddc2 1300 machine_mode mode,
f6a83b4a
DD
1301 tree type,
1302 bool named)
1303{
1304 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1305
1306 msp430_evaluate_arg (cap, mode, type, named);
1307
1308 if (ca->reg_count && ca->mem_count)
1309 return ca->reg_count * UNITS_PER_WORD;
1310
1311 return 0;
1312}
1313
1314#undef TARGET_PASS_BY_REFERENCE
1315#define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
1316
1317static bool
1318msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED,
ef4bddc2 1319 machine_mode mode,
f6a83b4a
DD
1320 const_tree type,
1321 bool named ATTRIBUTE_UNUSED)
1322{
1323 return (mode == BLKmode
1324 || (type && TREE_CODE (type) == RECORD_TYPE)
1325 || (type && TREE_CODE (type) == UNION_TYPE));
1326}
1327
1328#undef TARGET_CALLEE_COPIES
1329#define TARGET_CALLEE_COPIES msp430_callee_copies
1330
1331static bool
1332msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED,
ef4bddc2 1333 machine_mode mode ATTRIBUTE_UNUSED,
f6a83b4a
DD
1334 const_tree type ATTRIBUTE_UNUSED,
1335 bool named ATTRIBUTE_UNUSED)
1336{
1337 return true;
1338}
1339
1340#undef TARGET_FUNCTION_ARG_ADVANCE
1341#define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
1342
1343void
1344msp430_function_arg_advance (cumulative_args_t cap,
ef4bddc2 1345 machine_mode mode,
f6a83b4a
DD
1346 const_tree type,
1347 bool named)
1348{
1349 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1350 int i;
1351
1352 msp430_evaluate_arg (cap, mode, type, named);
1353
1354 if (ca->start_reg >= CA_FIRST_REG)
1355 for (i = 0; i < ca->reg_count; i ++)
1356 ca->reg_used [i + ca->start_reg - CA_FIRST_REG] = 1;
1357
1358 ca->special_p = 0;
1359}
1360
1361#undef TARGET_FUNCTION_ARG_BOUNDARY
1362#define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
1363
1364static unsigned int
ef4bddc2 1365msp430_function_arg_boundary (machine_mode mode, const_tree type)
f6a83b4a
DD
1366{
1367 if (mode == BLKmode
1368 && int_size_in_bytes (type) > 1)
1369 return 16;
1370 if (GET_MODE_BITSIZE (mode) > 8)
1371 return 16;
1372 return 8;
1373}
1374
1375#undef TARGET_RETURN_IN_MEMORY
1376#define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
1377
1378static bool
1379msp430_return_in_memory (const_tree ret_type, const_tree fntype ATTRIBUTE_UNUSED)
1380{
ef4bddc2 1381 machine_mode mode = TYPE_MODE (ret_type);
f6a83b4a
DD
1382
1383 if (mode == BLKmode
1384 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == RECORD_TYPE)
1385 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == UNION_TYPE))
1386 return true;
1387
1388 if (GET_MODE_SIZE (mode) > 8)
1389 return true;
1390
1391 return false;
1392}
1393
1394#undef TARGET_GET_RAW_ARG_MODE
1395#define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
1396
ef4bddc2 1397static machine_mode
f6a83b4a
DD
1398msp430_get_raw_arg_mode (int regno)
1399{
1400 return (regno == ARG_POINTER_REGNUM) ? VOIDmode : Pmode;
1401}
1402
1403#undef TARGET_GET_RAW_RESULT_MODE
1404#define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
1405
ef4bddc2 1406static machine_mode
f6a83b4a
DD
1407msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED)
1408{
1409 return Pmode;
1410}
467fc67c
NC
1411
1412#undef TARGET_GIMPLIFY_VA_ARG_EXPR
1413#define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
1414
1415#include "gimplify.h"
467fc67c
NC
1416
1417static tree
1418msp430_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
1419 gimple_seq *post_p)
1420{
1421 tree addr, t, type_size, rounded_size, valist_tmp;
1422 unsigned HOST_WIDE_INT align, boundary;
1423 bool indirect;
1424
1425 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
1426 if (indirect)
1427 type = build_pointer_type (type);
1428
1429 align = PARM_BOUNDARY / BITS_PER_UNIT;
1430 boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
1431
1432 /* When we align parameter on stack for caller, if the parameter
1433 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
1434 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
1435 here with caller. */
1436 if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
1437 boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
1438
1439 boundary /= BITS_PER_UNIT;
1440
1441 /* Hoist the valist value into a temporary for the moment. */
1442 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
1443
1444 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
1445 requires greater alignment, we must perform dynamic alignment. */
1446 if (boundary > align
1447 && !integer_zerop (TYPE_SIZE (type)))
1448 {
1449 /* FIXME: This is where this function diverts from targhooks.c:
1450 std_gimplify_va_arg_expr(). It works, but I do not know why... */
1451 if (! POINTER_TYPE_P (type))
1452 {
1453 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
1454 fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
1455 gimplify_and_add (t, pre_p);
1456
1457 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
1458 fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
1459 valist_tmp,
1460 build_int_cst (TREE_TYPE (valist), -boundary)));
1461 gimplify_and_add (t, pre_p);
1462 }
1463 }
1464 else
1465 boundary = align;
1466
1467 /* If the actual alignment is less than the alignment of the type,
1468 adjust the type accordingly so that we don't assume strict alignment
1469 when dereferencing the pointer. */
1470 boundary *= BITS_PER_UNIT;
1471 if (boundary < TYPE_ALIGN (type))
1472 {
1473 type = build_variant_type_copy (type);
fe37c7af 1474 SET_TYPE_ALIGN (type, boundary);
467fc67c
NC
1475 }
1476
1477 /* Compute the rounded size of the type. */
1478 type_size = size_in_bytes (type);
1479 rounded_size = round_up (type_size, align);
1480
1481 /* Reduce rounded_size so it's sharable with the postqueue. */
1482 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
1483
1484 /* Get AP. */
1485 addr = valist_tmp;
1486
1487 /* Compute new value for AP. */
1488 t = fold_build_pointer_plus (valist_tmp, rounded_size);
1489 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
1490 gimplify_and_add (t, pre_p);
1491
1492 addr = fold_convert (build_pointer_type (type), addr);
1493
1494 if (indirect)
1495 addr = build_va_arg_indirect_ref (addr);
1496
1497 addr = build_va_arg_indirect_ref (addr);
1498
1499 return addr;
1500}
f6a83b4a 1501\f
d81db636
SB
1502#undef TARGET_LRA_P
1503#define TARGET_LRA_P hook_bool_void_false
1504
f6a83b4a
DD
1505/* Addressing Modes */
1506
1507#undef TARGET_LEGITIMATE_ADDRESS_P
1508#define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
1509
1510static bool
1511reg_ok_for_addr (rtx r, bool strict)
1512{
1513 int rn = REGNO (r);
1514
1515 if (strict && rn >= FIRST_PSEUDO_REGISTER)
1516 rn = reg_renumber [rn];
1517 if (strict && 0 <= rn && rn < FIRST_PSEUDO_REGISTER)
1518 return true;
1519 if (!strict)
1520 return true;
1521 return false;
1522}
1523
1524bool
ef4bddc2 1525msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
f6a83b4a
DD
1526 rtx x ATTRIBUTE_UNUSED,
1527 bool strict ATTRIBUTE_UNUSED)
1528{
1529 switch (GET_CODE (x))
1530 {
1531 case MEM:
1532 return false;
1533
1534 case PLUS:
1535 if (REG_P (XEXP (x, 0)))
1536 {
1537 if (GET_MODE (x) != GET_MODE (XEXP (x, 0)))
1538 return false;
1539 if (!reg_ok_for_addr (XEXP (x, 0), strict))
1540 return false;
1541 switch (GET_CODE (XEXP (x, 1)))
1542 {
1543 case CONST:
1544 case SYMBOL_REF:
1545 case CONST_INT:
1546 return true;
1547 default:
1548 return false;
1549 }
1550 }
1551 return false;
1552
1553 case REG:
1554 if (!reg_ok_for_addr (x, strict))
1555 return false;
fcbe40f0 1556 /* FALLTHRU */
f6a83b4a
DD
1557 case CONST:
1558 case SYMBOL_REF:
1559 case CONST_INT:
1560 return true;
1561
1562 default:
1563 return false;
1564 }
1565}
1566
c32ab325
DD
1567#undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1568#define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
1569
1570bool
ef4bddc2 1571msp430_addr_space_legitimate_address_p (machine_mode mode,
c32ab325
DD
1572 rtx x,
1573 bool strict,
1574 addr_space_t as ATTRIBUTE_UNUSED)
1575{
1576 return msp430_legitimate_address_p (mode, x, strict);
1577}
1578
1579#undef TARGET_ASM_INTEGER
1580#define TARGET_ASM_INTEGER msp430_asm_integer
1581static bool
1582msp430_asm_integer (rtx x, unsigned int size, int aligned_p)
1583{
1584 int c = GET_CODE (x);
1585
1586 if (size == 3 && GET_MODE (x) == PSImode)
1587 size = 4;
1588
1589 switch (size)
1590 {
1591 case 4:
2bc43588
DD
1592 if (c == SYMBOL_REF || c == CONST || c == LABEL_REF || c == CONST_INT
1593 || c == PLUS || c == MINUS)
c32ab325
DD
1594 {
1595 fprintf (asm_out_file, "\t.long\t");
1596 output_addr_const (asm_out_file, x);
1597 fputc ('\n', asm_out_file);
1598 return true;
1599 }
1600 break;
1601 }
1602 return default_assemble_integer (x, size, aligned_p);
1603}
1604
1605#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
1606#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra
1607static bool
53fea787 1608msp430_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED, rtx x)
c32ab325
DD
1609{
1610 debug_rtx(x);
1611 return false;
1612}
1613
f6a83b4a
DD
1614#undef TARGET_LEGITIMATE_CONSTANT_P
1615#define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
1616
1617static bool
ef4bddc2 1618msp430_legitimate_constant (machine_mode mode, rtx x)
f6a83b4a
DD
1619{
1620 return ! CONST_INT_P (x)
1621 || mode != PSImode
1622 /* GCC does not know the width of the PSImode, so make
1623 sure that it does not try to use a constant value that
1624 is out of range. */
3ea7f8e5 1625 || (INTVAL (x) < (1 << 20) && INTVAL (x) >= (HOST_WIDE_INT)(HOST_WIDE_INT_M1U << 20));
f6a83b4a
DD
1626}
1627
1628\f
1629#undef TARGET_RTX_COSTS
1630#define TARGET_RTX_COSTS msp430_rtx_costs
1631
e548c9df
AM
1632static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED,
1633 machine_mode mode,
1634 int outer_code ATTRIBUTE_UNUSED,
1635 int opno ATTRIBUTE_UNUSED,
1636 int * total,
1637 bool speed ATTRIBUTE_UNUSED)
f6a83b4a 1638{
e548c9df
AM
1639 int code = GET_CODE (x);
1640
f6a83b4a
DD
1641 switch (code)
1642 {
1643 case SIGN_EXTEND:
e548c9df 1644 if (mode == SImode && outer_code == SET)
f6a83b4a
DD
1645 {
1646 *total = COSTS_N_INSNS (4);
1647 return true;
1648 }
1649 break;
1650 case ASHIFT:
1651 case ASHIFTRT:
1652 case LSHIFTRT:
1653 if (!msp430x)
1654 {
1655 *total = COSTS_N_INSNS (100);
1656 return true;
1657 }
1658 break;
1659 }
1660 return false;
1661}
1662\f
1663/* Function Entry and Exit */
1664
1665/* The MSP430 call frame looks like this:
1666
1667 <higher addresses>
1668 +--------------------+
1669 | |
1670 | Stack Arguments |
1671 | |
1672 +--------------------+ <-- "arg pointer"
1673 | |
1674 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
1675 | |
cad055a4
NC
1676 +--------------------+
1677 | SR if this func has|
1678 | been called via an |
1679 | interrupt. |
f6a83b4a
DD
1680 +--------------------+ <-- SP before prologue, also AP
1681 | |
1682 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
1683 | |
1684 +--------------------+ <-- "frame pointer"
1685 | |
1686 | Locals |
1687 | |
1688 +--------------------+
1689 | |
1690 | Outgoing Args |
1691 | |
1692 +--------------------+ <-- SP during function
1693 <lower addresses>
1694
1695*/
1696
1697/* We use this to wrap all emitted insns in the prologue, so they get
1698 the "frame-related" (/f) flag set. */
1699static rtx
1700F (rtx x)
1701{
1702 RTX_FRAME_RELATED_P (x) = 1;
1703 return x;
1704}
1705
1706/* This is the one spot that decides if a register is to be saved and
1707 restored in the prologue/epilogue. */
1708static bool
1709msp430_preserve_reg_p (int regno)
1710{
1711 /* PC, SP, SR, and the constant generator. */
1712 if (regno <= 3)
1713 return false;
1714
1715 /* FIXME: add interrupt, EH, etc. */
1716 if (crtl->calls_eh_return)
1717 return true;
1718
1719 /* Shouldn't be more than the above, but just in case... */
1720 if (fixed_regs [regno])
1721 return false;
1722
cad055a4
NC
1723 /* Interrupt handlers save all registers they use, even
1724 ones which are call saved. If they call other functions
1725 then *every* register is saved. */
1726 if (msp430_is_interrupt_func ())
1727 return ! crtl->is_leaf || df_regs_ever_live_p (regno);
1728
f6a83b4a
DD
1729 if (!call_used_regs [regno]
1730 && df_regs_ever_live_p (regno))
1731 return true;
1732
1733 return false;
1734}
1735
1736/* Compute all the frame-related fields in our machine_function
1737 structure. */
1738static void
1739msp430_compute_frame_info (void)
1740{
1741 int i;
1742
1743 cfun->machine->computed = 1;
1744 cfun->machine->framesize_regs = 0;
1745 cfun->machine->framesize_locals = get_frame_size ();
1746 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
1747
cad055a4 1748 for (i = 0; i < ARG_POINTER_REGNUM; i ++)
f6a83b4a
DD
1749 if (msp430_preserve_reg_p (i))
1750 {
1751 cfun->machine->need_to_save [i] = 1;
1752 cfun->machine->framesize_regs += (TARGET_LARGE ? 4 : 2);
1753 }
1754 else
1755 cfun->machine->need_to_save [i] = 0;
1756
1757 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
1758 cfun->machine->framesize_locals ++;
1759
1760 cfun->machine->framesize = (cfun->machine->framesize_regs
1761 + cfun->machine->framesize_locals
1762 + cfun->machine->framesize_outgoing);
1763}
1764
d7edde11
NC
1765/* Attribute Handling. */
1766
1767const char * const ATTR_INTR = "interrupt";
1768const char * const ATTR_WAKEUP = "wakeup";
1769const char * const ATTR_NAKED = "naked";
1770const char * const ATTR_REENT = "reentrant";
1771const char * const ATTR_CRIT = "critical";
1772const char * const ATTR_LOWER = "lower";
1773const char * const ATTR_UPPER = "upper";
1774const char * const ATTR_EITHER = "either";
90bc4878
NC
1775const char * const ATTR_NOINIT = "noinit";
1776const char * const ATTR_PERSIST = "persistent";
d7edde11 1777
cad055a4 1778static inline bool
d7edde11
NC
1779has_attr (const char * attr, tree decl)
1780{
1781 if (decl == NULL_TREE)
1782 return false;
1783 return lookup_attribute (attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
1784}
1785
1786static bool
1787is_interrupt_func (tree decl = current_function_decl)
cad055a4 1788{
d7edde11 1789 return has_attr (ATTR_INTR, decl);
cad055a4
NC
1790}
1791
1792/* Returns true if the current function has the "interrupt" attribute. */
1793
1794bool
1795msp430_is_interrupt_func (void)
1796{
d7edde11 1797 return is_interrupt_func (current_function_decl);
cad055a4
NC
1798}
1799
a005b5be 1800static bool
d7edde11 1801is_wakeup_func (tree decl = current_function_decl)
a005b5be 1802{
d7edde11 1803 return is_interrupt_func (decl) && has_attr (ATTR_WAKEUP, decl);
a005b5be
NC
1804}
1805
cad055a4 1806static inline bool
d7edde11 1807is_naked_func (tree decl = current_function_decl)
cad055a4 1808{
d7edde11 1809 return has_attr (ATTR_NAKED, decl);
cad055a4
NC
1810}
1811
1812static inline bool
d7edde11 1813is_reentrant_func (tree decl = current_function_decl)
cad055a4 1814{
d7edde11 1815 return has_attr (ATTR_REENT, decl);
cad055a4
NC
1816}
1817
1818static inline bool
d7edde11
NC
1819is_critical_func (tree decl = current_function_decl)
1820{
1821 return has_attr (ATTR_CRIT, decl);
1822}
1823
b3125625
JL
1824static bool
1825has_section_name (const char * name, tree decl = current_function_decl)
1826{
1827 if (decl == NULL_TREE)
1828 return false;
1829 return (DECL_SECTION_NAME (decl)
1830 && (strcmp (name, DECL_SECTION_NAME (decl)) == 0));
1831}
1832
d7edde11
NC
1833#undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
1834#define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS msp430_allocate_stack_slots_for_args
1835
1836static bool
1837msp430_allocate_stack_slots_for_args (void)
cad055a4 1838{
d7edde11
NC
1839 /* Naked functions should not allocate stack slots for arguments. */
1840 return ! is_naked_func ();
cad055a4
NC
1841}
1842
d7edde11
NC
1843/* Verify MSP430 specific attributes. */
1844#define TREE_NAME_EQ(NAME, STR) (strcmp (IDENTIFIER_POINTER (NAME), (STR)) == 0)
1845
1846static tree
1847msp430_attr (tree * node,
1848 tree name,
1849 tree args,
1850 int flags ATTRIBUTE_UNUSED,
1851 bool * no_add_attrs)
1852{
1853 gcc_assert (DECL_P (* node));
1854
1855 if (args != NULL)
1856 {
e56989ff 1857 /* Only the interrupt attribute takes an argument. */
d7edde11
NC
1858 gcc_assert (TREE_NAME_EQ (name, ATTR_INTR));
1859
1860 tree value = TREE_VALUE (args);
1861
1862 switch (TREE_CODE (value))
1863 {
1864 case STRING_CST:
1865 if ( strcmp (TREE_STRING_POINTER (value), "reset")
1866 && strcmp (TREE_STRING_POINTER (value), "nmi")
1867 && strcmp (TREE_STRING_POINTER (value), "watchdog"))
1868 /* Allow the attribute to be added - the linker script
1869 being used may still recognise this name. */
1870 warning (OPT_Wattributes,
bd2c6270 1871 "unrecognized interrupt vector argument of %qE attribute",
d7edde11
NC
1872 name);
1873 break;
1874
1875 case INTEGER_CST:
1876 if (wi::gtu_p (value, 63))
1877 /* Allow the attribute to be added - the linker script
1878 being used may still recognise this value. */
1879 warning (OPT_Wattributes,
1880 "numeric argument of %qE attribute must be in range 0..63",
1881 name);
1882 break;
1883
1884 default:
1885 warning (OPT_Wattributes,
1886 "argument of %qE attribute is not a string constant or number",
1887 name);
1888 *no_add_attrs = true;
1889 break;
1890 }
1891 }
1892
1893 const char * message = NULL;
1894
1895 if (TREE_CODE (* node) != FUNCTION_DECL)
1896 {
1897 message = "%qE attribute only applies to functions";
1898 }
1899 else if (TREE_NAME_EQ (name, ATTR_INTR))
1900 {
1901 if (TREE_CODE (TREE_TYPE (* node)) == FUNCTION_TYPE
1902 && ! VOID_TYPE_P (TREE_TYPE (TREE_TYPE (* node))))
1903 message = "interrupt handlers must be void";
e56989ff
NC
1904
1905 if (! TREE_PUBLIC (* node))
1906 message = "interrupt handlers cannot be static";
10bcba61
JL
1907
1908 /* Ensure interrupt handlers never get optimised out. */
1909 TREE_USED (* node) = 1;
1910 DECL_PRESERVE_P (* node) = 1;
d7edde11
NC
1911 }
1912 else if (TREE_NAME_EQ (name, ATTR_REENT))
1913 {
1914 if (is_naked_func (* node))
1915 message = "naked functions cannot be reentrant";
1916 else if (is_critical_func (* node))
1917 message = "critical functions cannot be reentrant";
1918 }
1919 else if (TREE_NAME_EQ (name, ATTR_CRIT))
1920 {
1921 if (is_naked_func (* node))
1922 message = "naked functions cannot be critical";
1923 else if (is_reentrant_func (* node))
90bc4878 1924 message = "reentrant functions cannot be critical";
d7edde11
NC
1925 }
1926 else if (TREE_NAME_EQ (name, ATTR_NAKED))
1927 {
1928 if (is_critical_func (* node))
1929 message = "critical functions cannot be naked";
1930 else if (is_reentrant_func (* node))
1931 message = "reentrant functions cannot be naked";
1932 }
1933
1934 if (message)
1935 {
1936 warning (OPT_Wattributes, message, name);
1937 * no_add_attrs = true;
1938 }
1939
1940 return NULL_TREE;
1941}
1942
1943static tree
1944msp430_section_attr (tree * node,
1945 tree name,
1946 tree args,
1947 int flags ATTRIBUTE_UNUSED,
1948 bool * no_add_attrs ATTRIBUTE_UNUSED)
1949{
1950 gcc_assert (DECL_P (* node));
1951 gcc_assert (args == NULL);
1952
1953 const char * message = NULL;
1954
1955 if (TREE_NAME_EQ (name, ATTR_UPPER))
1956 {
1957 if (has_attr (ATTR_LOWER, * node))
1958 message = "already marked with 'lower' attribute";
1959 else if (has_attr (ATTR_EITHER, * node))
1960 message = "already marked with 'either' attribute";
1961 else if (! msp430x)
1962 message = "upper attribute needs a 430X cpu";
1963 }
1964 else if (TREE_NAME_EQ (name, ATTR_LOWER))
1965 {
1966 if (has_attr (ATTR_UPPER, * node))
1967 message = "already marked with 'upper' attribute";
1968 else if (has_attr (ATTR_EITHER, * node))
1969 message = "already marked with 'either' attribute";
1970 }
1971 else
1972 {
1973 gcc_assert (TREE_NAME_EQ (name, ATTR_EITHER));
1974
1975 if (has_attr (ATTR_LOWER, * node))
1976 message = "already marked with 'lower' attribute";
1977 else if (has_attr (ATTR_UPPER, * node))
1978 message = "already marked with 'upper' attribute";
1979 }
1980
1981 if (message)
1982 {
1983 warning (OPT_Wattributes, message, name);
1984 * no_add_attrs = true;
1985 }
1986
1987 return NULL_TREE;
1988}
1989
90bc4878
NC
1990static tree
1991msp430_data_attr (tree * node,
1992 tree name,
1993 tree args,
1994 int flags ATTRIBUTE_UNUSED,
1995 bool * no_add_attrs ATTRIBUTE_UNUSED)
1996{
1997 const char * message = NULL;
1998
1999 gcc_assert (DECL_P (* node));
2000 gcc_assert (args == NULL);
2001
2002 if (TREE_CODE (* node) != VAR_DECL)
61f5d852
JL
2003 message = G_("%qE attribute only applies to variables");
2004
2005 /* Check that it's possible for the variable to have a section. */
2006 if ((TREE_STATIC (* node) || DECL_EXTERNAL (* node) || in_lto_p)
2007 && DECL_SECTION_NAME (* node))
2008 message = G_("%qE attribute cannot be applied to variables with specific sections");
2009
2010 if (!message && TREE_NAME_EQ (name, ATTR_PERSIST) && !TREE_STATIC (* node)
2011 && !TREE_PUBLIC (* node) && !DECL_EXTERNAL (* node))
2012 message = G_("%qE attribute has no effect on automatic variables");
2013
2014 /* It's not clear if there is anything that can be set here to prevent the
2015 front end placing the variable before the back end can handle it, in a
2016 similar way to how DECL_COMMON is used below.
2017 So just place the variable in the .persistent section now. */
2018 if ((TREE_STATIC (* node) || DECL_EXTERNAL (* node) || in_lto_p)
2019 && TREE_NAME_EQ (name, ATTR_PERSIST))
2020 set_decl_section_name (* node, ".persistent");
90bc4878
NC
2021
2022 /* If this var is thought to be common, then change this. Common variables
2023 are assigned to sections before the backend has a chance to process them. */
2024 if (DECL_COMMON (* node))
2025 DECL_COMMON (* node) = 0;
2026
2027 if (message)
2028 {
2029 warning (OPT_Wattributes, message, name);
2030 * no_add_attrs = true;
2031 }
2032
2033 return NULL_TREE;
2034}
2035
2036
d7edde11
NC
2037#undef TARGET_ATTRIBUTE_TABLE
2038#define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
2039
2040/* Table of MSP430-specific attributes. */
2041const struct attribute_spec msp430_attribute_table[] =
2042{
2043 /* Name min_num_args type_req, affects_type_identity
2044 max_num_args, fn_type_req
2045 decl_req handler. */
2046 { ATTR_INTR, 0, 1, true, false, false, msp430_attr, false },
2047 { ATTR_NAKED, 0, 0, true, false, false, msp430_attr, false },
2048 { ATTR_REENT, 0, 0, true, false, false, msp430_attr, false },
2049 { ATTR_CRIT, 0, 0, true, false, false, msp430_attr, false },
2050 { ATTR_WAKEUP, 0, 0, true, false, false, msp430_attr, false },
2051
2052 { ATTR_LOWER, 0, 0, true, false, false, msp430_section_attr, false },
2053 { ATTR_UPPER, 0, 0, true, false, false, msp430_section_attr, false },
2054 { ATTR_EITHER, 0, 0, true, false, false, msp430_section_attr, false },
2055
90bc4878
NC
2056 { ATTR_NOINIT, 0, 0, true, false, false, msp430_data_attr, false },
2057 { ATTR_PERSIST, 0, 0, true, false, false, msp430_data_attr, false },
2058
04a9ae28 2059 { NULL, 0, 0, false, false, false, NULL, false }
d7edde11
NC
2060};
2061
f6a83b4a
DD
2062#undef TARGET_ASM_FUNCTION_PROLOGUE
2063#define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
2064
2065static void
42776416 2066msp430_start_function (FILE *outfile)
f6a83b4a
DD
2067{
2068 int r, n;
2069
2070 fprintf (outfile, "; start of function\n");
cad055a4
NC
2071
2072 if (DECL_ATTRIBUTES (current_function_decl) != NULL_TREE)
2073 {
2074 fprintf (outfile, "; attributes: ");
2075 if (is_naked_func ())
2076 fprintf (outfile, "naked ");
2077 if (msp430_is_interrupt_func ())
2078 fprintf (outfile, "interrupt ");
2079 if (is_reentrant_func ())
2080 fprintf (outfile, "reentrant ");
2081 if (is_critical_func ())
2082 fprintf (outfile, "critical ");
a005b5be
NC
2083 if (is_wakeup_func ())
2084 fprintf (outfile, "wakeup ");
cad055a4
NC
2085 fprintf (outfile, "\n");
2086 }
2087
f6a83b4a
DD
2088 fprintf (outfile, "; framesize_regs: %d\n", cfun->machine->framesize_regs);
2089 fprintf (outfile, "; framesize_locals: %d\n", cfun->machine->framesize_locals);
2090 fprintf (outfile, "; framesize_outgoing: %d\n", cfun->machine->framesize_outgoing);
2091 fprintf (outfile, "; framesize: %d\n", cfun->machine->framesize);
2092 fprintf (outfile, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM));
2093 fprintf (outfile, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM));
2094
2095 n = 0;
2096 fprintf (outfile, "; saved regs:");
cad055a4 2097 for (r = 0; r < ARG_POINTER_REGNUM; r++)
f6a83b4a
DD
2098 if (cfun->machine->need_to_save [r])
2099 {
2100 fprintf (outfile, " %s", reg_names [r]);
2101 n = 1;
2102 }
2103 if (n == 0)
2104 fprintf (outfile, "(none)");
2105 fprintf (outfile, "\n");
2106}
2107
2108/* Common code to change the stack pointer. */
2109static void
2110increment_stack (HOST_WIDE_INT amount)
2111{
2112 rtx inc;
2113 rtx sp = stack_pointer_rtx;
2114
2115 if (amount == 0)
2116 return;
2117
2118 if (amount < 0)
2119 {
2120 inc = GEN_INT (- amount);
2121 if (TARGET_LARGE)
2122 F (emit_insn (gen_subpsi3 (sp, sp, inc)));
2123 else
2124 F (emit_insn (gen_subhi3 (sp, sp, inc)));
2125 }
2126 else
2127 {
2128 inc = GEN_INT (amount);
2129 if (TARGET_LARGE)
2130 emit_insn (gen_addpsi3 (sp, sp, inc));
2131 else
2132 emit_insn (gen_addhi3 (sp, sp, inc));
2133 }
2134}
2135
cad055a4
NC
2136void
2137msp430_start_function (FILE *file, const char *name, tree decl)
2138{
2139 tree int_attr;
2140
2141 int_attr = lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl));
2142 if (int_attr != NULL_TREE)
2143 {
2144 tree intr_vector = TREE_VALUE (int_attr);
2145
2146 if (intr_vector != NULL_TREE)
2147 {
2148 char buf[101];
2149
a713b234
JS
2150 /* Interrupt vector sections should be unique, but use of weak
2151 functions implies multiple definitions. */
2152 if (DECL_WEAK (decl))
2153 {
2154 error ("argument to interrupt attribute is unsupported for weak functions");
2155 }
2156
cad055a4
NC
2157 intr_vector = TREE_VALUE (intr_vector);
2158
2159 /* The interrupt attribute has a vector value. Turn this into a
2160 section name, switch to that section and put the address of
2161 the current function into that vector slot. Note msp430_attr()
2162 has already verified the vector name for us. */
2163 if (TREE_CODE (intr_vector) == STRING_CST)
2164 sprintf (buf, "__interrupt_vector_%.80s",
2165 TREE_STRING_POINTER (intr_vector));
2166 else /* TREE_CODE (intr_vector) == INTEGER_CST */
2167 sprintf (buf, "__interrupt_vector_%u",
2168 (unsigned int) TREE_INT_CST_LOW (intr_vector));
2169
2170 switch_to_section (get_section (buf, SECTION_CODE, decl));
2171 fputs ("\t.word\t", file);
2172 assemble_name (file, name);
2173 fputc ('\n', file);
2174 fputc ('\t', file);
2175 }
2176 }
2177
2178 switch_to_section (function_section (decl));
d094128b 2179 ASM_OUTPUT_TYPE_DIRECTIVE(file, name, "function");
cad055a4
NC
2180 ASM_OUTPUT_FUNCTION_LABEL (file, name, decl);
2181}
2182
d7edde11
NC
2183static const char * const lower_prefix = ".lower";
2184static const char * const upper_prefix = ".upper";
2185static const char * const either_prefix = ".either";
2186
2187/* Generate a prefix for a section name, based upon
2188 the region into which the object should be placed. */
2189
2190static const char *
2191gen_prefix (tree decl)
2192{
2193 if (DECL_ONE_ONLY (decl))
2194 return NULL;
2195
2196 /* If the user has specified a particular section then do not use any prefix. */
2197 if (has_attr ("section", decl))
2198 return NULL;
2199
b3125625
JL
2200 /* If the function has been put in the .lowtext section (because it is an
2201 interrupt handler, and the large memory model is used), then do not add
2202 any prefixes. */
2203 if (has_section_name (".lowtext", decl))
2204 return NULL;
2205
d7edde11
NC
2206 /* If the object has __attribute__((lower)) then use the ".lower." prefix. */
2207 if (has_attr (ATTR_LOWER, decl))
2208 return lower_prefix;
2209
2210 /* If we are compiling for the MSP430 then we do not support the upper region. */
2211 if (! msp430x)
2212 return NULL;
2213
2214 if (has_attr (ATTR_UPPER, decl))
2215 return upper_prefix;
2216
2217 if (has_attr (ATTR_EITHER, decl))
2218 return either_prefix;
2219
2220 if (TREE_CODE (decl) == FUNCTION_DECL)
2221 {
b07447ba 2222 if (msp430_code_region == MSP430_REGION_LOWER)
d7edde11
NC
2223 return lower_prefix;
2224
b07447ba 2225 if (msp430_code_region == MSP430_REGION_UPPER)
d7edde11
NC
2226 return upper_prefix;
2227
b07447ba 2228 if (msp430_code_region == MSP430_REGION_EITHER)
d7edde11
NC
2229 return either_prefix;
2230 }
2231 else
2232 {
b07447ba 2233 if (msp430_data_region == MSP430_REGION_LOWER)
d7edde11
NC
2234 return lower_prefix;
2235
b07447ba 2236 if (msp430_data_region == MSP430_REGION_UPPER)
d7edde11
NC
2237 return upper_prefix;
2238
b07447ba 2239 if (msp430_data_region == MSP430_REGION_EITHER)
d7edde11
NC
2240 return either_prefix;
2241 }
2242
2243 return NULL;
2244}
2245
90bc4878
NC
2246static section * noinit_section;
2247static section * persist_section;
2248
2249#undef TARGET_ASM_INIT_SECTIONS
2250#define TARGET_ASM_INIT_SECTIONS msp430_init_sections
2251
2252static void
2253msp430_init_sections (void)
2254{
2255 noinit_section = get_unnamed_section (0, output_section_asm_op, ".section .noinit,\"aw\"");
2256 persist_section = get_unnamed_section (0, output_section_asm_op, ".section .persistent,\"aw\"");
2257}
2258
d7edde11
NC
2259#undef TARGET_ASM_SELECT_SECTION
2260#define TARGET_ASM_SELECT_SECTION msp430_select_section
2261
cad055a4 2262static section *
d7edde11 2263msp430_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
cad055a4 2264{
d7edde11
NC
2265 gcc_assert (decl != NULL_TREE);
2266
2267 if (TREE_CODE (decl) == STRING_CST
2268 || TREE_CODE (decl) == CONSTRUCTOR
2269 || TREE_CODE (decl) == INTEGER_CST
2270 || TREE_CODE (decl) == VECTOR_CST
2271 || TREE_CODE (decl) == COMPLEX_CST)
2272 return default_select_section (decl, reloc, align);
2273
cad055a4
NC
2274 /* In large mode we must make sure that interrupt handlers are put into
2275 low memory as the vector table only accepts 16-bit addresses. */
d7edde11 2276 if (TARGET_LARGE && TREE_CODE (decl) == FUNCTION_DECL && is_interrupt_func (decl))
cad055a4
NC
2277 return get_section (".lowtext", SECTION_CODE | SECTION_WRITE , decl);
2278
d7edde11
NC
2279 const char * prefix = gen_prefix (decl);
2280 if (prefix == NULL)
2281 {
2282 if (TREE_CODE (decl) == FUNCTION_DECL)
2283 return text_section;
90bc4878
NC
2284 else if (has_attr (ATTR_NOINIT, decl))
2285 return noinit_section;
2286 else if (has_attr (ATTR_PERSIST, decl))
2287 return persist_section;
d7edde11
NC
2288 else
2289 return default_select_section (decl, reloc, align);
2290 }
2291
2292 const char * sec;
2293 switch (categorize_decl_for_section (decl, reloc))
2294 {
2295 case SECCAT_TEXT: sec = ".text"; break;
2296 case SECCAT_DATA: sec = ".data"; break;
2297 case SECCAT_BSS: sec = ".bss"; break;
2298 case SECCAT_RODATA: sec = ".rodata"; break;
2299
2300 case SECCAT_RODATA_MERGE_STR:
2301 case SECCAT_RODATA_MERGE_STR_INIT:
2302 case SECCAT_RODATA_MERGE_CONST:
2303 case SECCAT_SRODATA:
2304 case SECCAT_DATA_REL:
2305 case SECCAT_DATA_REL_LOCAL:
2306 case SECCAT_DATA_REL_RO:
2307 case SECCAT_DATA_REL_RO_LOCAL:
2308 case SECCAT_SDATA:
2309 case SECCAT_SBSS:
2310 case SECCAT_TDATA:
2311 case SECCAT_TBSS:
2312 return default_select_section (decl, reloc, align);
2313
2314 default:
2315 gcc_unreachable ();
2316 }
2317
2318 const char * dec_name = DECL_SECTION_NAME (decl);
2319 char * name = ACONCAT ((prefix, sec, dec_name, NULL));
2320
2321 return get_named_section (decl, name, 0);
cad055a4
NC
2322}
2323
2324#undef TARGET_ASM_FUNCTION_SECTION
2325#define TARGET_ASM_FUNCTION_SECTION msp430_function_section
2326
d7edde11
NC
2327static section *
2328msp430_function_section (tree decl, enum node_frequency freq, bool startup, bool exit)
2329{
2330 const char * name;
2331
2332 gcc_assert (DECL_SECTION_NAME (decl) != NULL);
2333 name = DECL_SECTION_NAME (decl);
2334
2335 const char * prefix = gen_prefix (decl);
2336 if (prefix == NULL
2337 || strncmp (name, prefix, strlen (prefix)) == 0)
2338 return default_function_section (decl, freq, startup, exit);
2339
2340 name = ACONCAT ((prefix, name, NULL));
2341 return get_named_section (decl, name, 0);
2342}
2343
2344#undef TARGET_SECTION_TYPE_FLAGS
2345#define TARGET_SECTION_TYPE_FLAGS msp430_section_type_flags
2346
2347unsigned int
2348msp430_section_type_flags (tree decl, const char * name, int reloc)
2349{
2350 if (strncmp (name, lower_prefix, strlen (lower_prefix)) == 0)
2351 name += strlen (lower_prefix);
2352 else if (strncmp (name, upper_prefix, strlen (upper_prefix)) == 0)
2353 name += strlen (upper_prefix);
2354 else if (strncmp (name, either_prefix, strlen (either_prefix)) == 0)
2355 name += strlen (either_prefix);
90bc4878
NC
2356 else if (strcmp (name, ".noinit") == 0)
2357 return SECTION_WRITE | SECTION_BSS | SECTION_NOTYPE;
aad11912 2358 else if (strcmp (name, ".persistent") == 0)
90bc4878
NC
2359 return SECTION_WRITE | SECTION_NOTYPE;
2360
d7edde11
NC
2361 return default_section_type_flags (decl, name, reloc);
2362}
2363
2364#undef TARGET_ASM_UNIQUE_SECTION
2365#define TARGET_ASM_UNIQUE_SECTION msp430_unique_section
2366
2367static void
2368msp430_unique_section (tree decl, int reloc)
2369{
2370 gcc_assert (decl != NULL_TREE);
2371
2372 /* In large mode we must make sure that interrupt handlers are put into
2373 low memory as the vector table only accepts 16-bit addresses. */
2374 if (TARGET_LARGE && TREE_CODE (decl) == FUNCTION_DECL && is_interrupt_func (decl))
2375 {
2376 set_decl_section_name (decl, ".lowtext");
2377 return;
2378 }
2379
2380 default_unique_section (decl, reloc);
2381
2382 const char * prefix;
2383
2384 if ( TREE_CODE (decl) == STRING_CST
2385 || TREE_CODE (decl) == CONSTRUCTOR
2386 || TREE_CODE (decl) == INTEGER_CST
2387 || TREE_CODE (decl) == VECTOR_CST
2388 || TREE_CODE (decl) == COMPLEX_CST
2389 || (prefix = gen_prefix (decl)) == NULL
2390 )
2391 return;
2392
2393 const char * dec_name = DECL_SECTION_NAME (decl);
2394 char * name = ACONCAT ((prefix, dec_name, NULL));
2395
2396 set_decl_section_name (decl, name);
2397}
2398
2399/* Emit a declaration of a common symbol.
2400 If a data region is in use then put the symbol into the
2401 equivalent .bss section instead. */
2402
2403void
2404msp430_output_aligned_decl_common (FILE * stream,
2405 const tree decl,
2406 const char * name,
2407 unsigned HOST_WIDE_INT size,
2408 unsigned int align)
2409{
b07447ba 2410 if (msp430_data_region == MSP430_REGION_ANY)
d7edde11
NC
2411 {
2412 fprintf (stream, COMMON_ASM_OP);
2413 assemble_name (stream, name);
16998094 2414 fprintf (stream, "," HOST_WIDE_INT_PRINT_UNSIGNED",%u\n",
d7edde11
NC
2415 size, align / BITS_PER_UNIT);
2416 }
2417 else
2418 {
2419 section * sec;
2420
2421 if (decl)
2422 sec = msp430_select_section (decl, 0, align);
2423 else
2424 switch (msp430_data_region)
2425 {
b07447ba
NC
2426 case MSP430_REGION_UPPER: sec = get_named_section (NULL, ".upper.bss", 0); break;
2427 case MSP430_REGION_LOWER: sec = get_named_section (NULL, ".lower.bss", 0); break;
2428 case MSP430_REGION_EITHER: sec = get_named_section (NULL, ".either.bss", 0); break;
d7edde11
NC
2429 default:
2430 gcc_unreachable ();
2431 }
2432 gcc_assert (sec != NULL);
2433
2434 switch_to_section (sec);
2435 ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
2436 targetm.asm_out.globalize_label (stream, name);
2437 ASM_WEAKEN_LABEL (stream, name);
2438 ASM_OUTPUT_LABEL (stream, name);
2439 ASM_OUTPUT_SKIP (stream, size ? size : 1);
2440 }
2441}
2442
2443bool
2444msp430_do_not_relax_short_jumps (void)
2445{
2446 /* When placing code into "either" low or high memory we do not want the linker
2447 to grow the size of sections, which it can do if it is encounters a branch to
2448 a label that is too far away. So we tell the cbranch patterns to avoid using
2449 short jumps when there is a chance that the instructions will end up in a low
2450 section. */
2451 return
b07447ba
NC
2452 msp430_code_region == MSP430_REGION_EITHER
2453 || msp430_code_region == MSP430_REGION_LOWER
d7edde11
NC
2454 || has_attr (ATTR_EITHER, current_function_decl)
2455 || has_attr (ATTR_LOWER, current_function_decl);
2456}
2457
cad055a4
NC
2458enum msp430_builtin
2459{
2460 MSP430_BUILTIN_BIC_SR,
2461 MSP430_BUILTIN_BIS_SR,
5f35dde5 2462 MSP430_BUILTIN_DELAY_CYCLES,
cad055a4
NC
2463 MSP430_BUILTIN_max
2464};
2465
2466static GTY(()) tree msp430_builtins [(int) MSP430_BUILTIN_max];
2467
2468static void
2469msp430_init_builtins (void)
2470{
2471 tree void_ftype_int = build_function_type_list (void_type_node, integer_type_node, NULL);
5f35dde5 2472 tree void_ftype_longlong = build_function_type_list (void_type_node, long_long_integer_type_node, NULL);
cad055a4
NC
2473
2474 msp430_builtins[MSP430_BUILTIN_BIC_SR] =
2475 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int,
2476 MSP430_BUILTIN_BIC_SR, BUILT_IN_MD, NULL, NULL_TREE);
2477
2478 msp430_builtins[MSP430_BUILTIN_BIS_SR] =
2479 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int,
2480 MSP430_BUILTIN_BIS_SR, BUILT_IN_MD, NULL, NULL_TREE);
5f35dde5
DD
2481
2482 msp430_builtins[MSP430_BUILTIN_DELAY_CYCLES] =
2483 add_builtin_function ( "__delay_cycles", void_ftype_longlong,
2484 MSP430_BUILTIN_DELAY_CYCLES, BUILT_IN_MD, NULL, NULL_TREE);
cad055a4
NC
2485}
2486
2487static tree
2488msp430_builtin_decl (unsigned code, bool initialize ATTRIBUTE_UNUSED)
2489{
2490 switch (code)
2491 {
2492 case MSP430_BUILTIN_BIC_SR:
2493 case MSP430_BUILTIN_BIS_SR:
5f35dde5 2494 case MSP430_BUILTIN_DELAY_CYCLES:
cad055a4
NC
2495 return msp430_builtins[code];
2496 default:
2497 return error_mark_node;
2498 }
2499}
2500
5f35dde5
DD
2501/* These constants are really register reads, which are faster than
2502 regular constants. */
2503static int
2504cg_magic_constant (HOST_WIDE_INT c)
2505{
2506 switch (c)
2507 {
2508 case 0xffff:
2509 case -1:
2510 case 0:
2511 case 1:
2512 case 2:
2513 case 4:
2514 case 8:
2515 return 1;
2516 default:
2517 return 0;
2518 }
2519}
2520
2521static rtx
2522msp430_expand_delay_cycles (rtx arg)
2523{
2524 HOST_WIDE_INT i, c, n;
2525 /* extra cycles for MSP430X instructions */
2526#define CYCX(M,X) (msp430x ? (X) : (M))
2527
2528 if (GET_CODE (arg) != CONST_INT)
2529 {
2530 error ("__delay_cycles() only takes constant arguments");
2531 return NULL_RTX;
2532 }
2533
2534 c = INTVAL (arg);
2535
2536 if (HOST_BITS_PER_WIDE_INT > 32)
2537 {
2538 if (c < 0)
2539 {
90aaff2c 2540 error ("__delay_cycles only takes non-negative cycle counts");
5f35dde5
DD
2541 return NULL_RTX;
2542 }
2543 }
2544
2545 emit_insn (gen_delay_cycles_start (arg));
2546
2547 /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
2548 if (c > 3 * 0xffff + CYCX (7, 10))
2549 {
2550 n = c;
2551 /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
2552 if (c >= 0x10000 * 7 + CYCX (14, 16))
2553 {
2554 i = 0x10000;
2555 c -= CYCX (14, 16) + 7 * 0x10000;
2556 i += c / 4;
2557 c %= 4;
2558 if ((unsigned long long) i > 0xffffffffULL)
2559 {
90aaff2c 2560 error ("__delay_cycles is limited to 32-bit loop counts");
5f35dde5
DD
2561 return NULL_RTX;
2562 }
2563 }
2564 else
2565 {
2566 i = (c - CYCX (14, 16)) / 7;
2567 c -= CYCX (14, 16) + i * 7;
2568 }
2569
2570 if (cg_magic_constant (i & 0xffff))
2571 c ++;
2572 if (cg_magic_constant ((i >> 16) & 0xffff))
2573 c ++;
2574
2575 if (msp430x)
2576 emit_insn (gen_delay_cycles_32x (GEN_INT (i), GEN_INT (n - c)));
2577 else
2578 emit_insn (gen_delay_cycles_32 (GEN_INT (i), GEN_INT (n - c)));
2579 }
2580
2581 /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
2582 if (c > 12)
2583 {
2584 n = c;
2585 i = (c - CYCX (7, 10)) / 3;
2586 c -= CYCX (7, 10) + i * 3;
2587
2588 if (cg_magic_constant (i))
2589 c ++;
2590
2591 if (msp430x)
2592 emit_insn (gen_delay_cycles_16x (GEN_INT (i), GEN_INT (n - c)));
2593 else
2594 emit_insn (gen_delay_cycles_16 (GEN_INT (i), GEN_INT (n - c)));
2595 }
2596
2597 while (c > 1)
2598 {
2599 emit_insn (gen_delay_cycles_2 ());
2600 c -= 2;
2601 }
2602
2603 if (c)
2604 {
2605 emit_insn (gen_delay_cycles_1 ());
2606 c -= 1;
2607 }
2608
2609 emit_insn (gen_delay_cycles_end (arg));
2610
2611 return NULL_RTX;
2612}
2613
cad055a4
NC
2614static rtx
2615msp430_expand_builtin (tree exp,
2616 rtx target ATTRIBUTE_UNUSED,
2617 rtx subtarget ATTRIBUTE_UNUSED,
ef4bddc2 2618 machine_mode mode ATTRIBUTE_UNUSED,
cad055a4
NC
2619 int ignore ATTRIBUTE_UNUSED)
2620{
2621 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
2622 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2623 rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
2624
5f35dde5
DD
2625 if (fcode == MSP430_BUILTIN_DELAY_CYCLES)
2626 return msp430_expand_delay_cycles (arg1);
2627
cad055a4
NC
2628 if (! msp430_is_interrupt_func ())
2629 {
2630 error ("MSP430 builtin functions only work inside interrupt handlers");
2631 return NULL_RTX;
2632 }
2633
2634 if (! REG_P (arg1) && ! CONSTANT_P (arg1))
2635 arg1 = force_reg (mode, arg1);
2636
2637 switch (fcode)
2638 {
2639 case MSP430_BUILTIN_BIC_SR: emit_insn (gen_bic_SR (arg1)); break;
2640 case MSP430_BUILTIN_BIS_SR: emit_insn (gen_bis_SR (arg1)); break;
2641 default:
2642 internal_error ("bad builtin code");
2643 break;
2644 }
2645 return NULL_RTX;
2646}
2647
2648#undef TARGET_INIT_BUILTINS
2649#define TARGET_INIT_BUILTINS msp430_init_builtins
2650
2651#undef TARGET_EXPAND_BUILTIN
2652#define TARGET_EXPAND_BUILTIN msp430_expand_builtin
2653
2654#undef TARGET_BUILTIN_DECL
2655#define TARGET_BUILTIN_DECL msp430_builtin_decl
2656
f6a83b4a
DD
2657void
2658msp430_expand_prologue (void)
2659{
2660 int i, j;
2661 int fs;
2662 /* Always use stack_pointer_rtx instead of calling
2663 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
2664 that there is a single rtx representing the stack pointer,
2665 namely stack_pointer_rtx, and uses == to recognize it. */
2666 rtx sp = stack_pointer_rtx;
2667 rtx p;
2668
cad055a4 2669 if (is_naked_func ())
f642a8b7
NC
2670 {
2671 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2672 examines the output of the gen_prologue() function. */
2673 emit_insn (gen_rtx_CLOBBER (VOIDmode, GEN_INT (0)));
2674 return;
2675 }
cad055a4 2676
f6a83b4a
DD
2677 emit_insn (gen_prologue_start_marker ());
2678
cad055a4
NC
2679 if (is_critical_func ())
2680 {
2681 emit_insn (gen_push_intr_state ());
2682 emit_insn (gen_disable_interrupts ());
2683 }
2684 else if (is_reentrant_func ())
2685 emit_insn (gen_disable_interrupts ());
2686
f6a83b4a
DD
2687 if (!cfun->machine->computed)
2688 msp430_compute_frame_info ();
2689
2690 if (flag_stack_usage_info)
2691 current_function_static_stack_size = cfun->machine->framesize;
c6f709ec 2692
f6a83b4a
DD
2693 if (crtl->args.pretend_args_size)
2694 {
2695 rtx note;
2696
2697 gcc_assert (crtl->args.pretend_args_size == 2);
c6f709ec 2698
f6a83b4a
DD
2699 p = emit_insn (gen_grow_and_swap ());
2700
2701 /* Document the stack decrement... */
f7df4a84 2702 note = F (gen_rtx_SET (stack_pointer_rtx,
f6a83b4a
DD
2703 gen_rtx_MINUS (Pmode, stack_pointer_rtx, GEN_INT (2))));
2704 add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
2705
2706 /* ...and the establishment of a new location for the return address. */
f7df4a84
RS
2707 note = F (gen_rtx_SET (gen_rtx_MEM (Pmode,
2708 gen_rtx_PLUS (Pmode,
2709 stack_pointer_rtx,
2710 GEN_INT (-2))),
f6a83b4a
DD
2711 pc_rtx));
2712 add_reg_note (p, REG_CFA_OFFSET, note);
2713 F (p);
2714 }
2715
2716 for (i = 15; i >= 4; i--)
2717 if (cfun->machine->need_to_save [i])
2718 {
2719 int seq, count;
2720 rtx note;
2721
2722 for (seq = i - 1; seq >= 4 && cfun->machine->need_to_save[seq]; seq --)
2723 ;
2724 count = i - seq;
2725
2726 if (msp430x)
2727 {
2728 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
2729 p = F (emit_insn (gen_pushm (gen_rtx_REG (Pmode, i),
2730 GEN_INT (count))));
2731
2732 note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1));
2733
2734 XVECEXP (note, 0, 0)
f7df4a84
RS
2735 = F (gen_rtx_SET (stack_pointer_rtx,
2736 gen_rtx_PLUS (Pmode,
2737 stack_pointer_rtx,
2738 GEN_INT (count * (TARGET_LARGE ? -4 : -2)))));
f6a83b4a
DD
2739
2740 /* *sp-- = R[i-j] */
2741 /* sp+N R10
2742 ...
2743 sp R4 */
2744 for (j = 0; j < count; j ++)
2745 {
2746 rtx addr;
2747 int ofs = (count - j - 1) * (TARGET_LARGE ? 4 : 2);
2748
2749 if (ofs)
2750 addr = gen_rtx_PLUS (Pmode, sp, GEN_INT (ofs));
2751 else
2752 addr = stack_pointer_rtx;
2753
c6f709ec 2754 XVECEXP (note, 0, j + 1) =
f7df4a84 2755 F (gen_rtx_SET (gen_rtx_MEM (Pmode, addr),
f6a83b4a
DD
2756 gen_rtx_REG (Pmode, i - j)) );
2757 }
2758
2759 add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
2760 i -= count - 1;
2761 }
2762 else
2763 F (emit_insn (gen_push (gen_rtx_REG (Pmode, i))));
2764 }
2765
2766 if (frame_pointer_needed)
2767 F (emit_move_insn (gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM), sp));
2768
2769 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
2770
2771 increment_stack (- fs);
2772
2773 emit_insn (gen_prologue_end_marker ());
2774}
2775
2776void
2777msp430_expand_epilogue (int is_eh)
2778{
2779 int i;
2780 int fs;
2781 int helper_n = 0;
2782
cad055a4 2783 if (is_naked_func ())
f642a8b7
NC
2784 {
2785 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2786 examines the output of the gen_epilogue() function. */
2787 emit_insn (gen_rtx_CLOBBER (VOIDmode, GEN_INT (0)));
2788 return;
2789 }
cad055a4 2790
f6a83b4a
DD
2791 if (cfun->machine->need_to_save [10])
2792 {
2793 /* Check for a helper function. */
40ada30a 2794 helper_n = 7; /* For when the loop below never sees a match. */
f6a83b4a
DD
2795 for (i = 9; i >= 4; i--)
2796 if (!cfun->machine->need_to_save [i])
2797 {
2798 helper_n = 10 - i;
2799 for (; i >= 4; i--)
2800 if (cfun->machine->need_to_save [i])
2801 {
2802 helper_n = 0;
2803 break;
2804 }
2805 break;
2806 }
2807 }
2808
2809 emit_insn (gen_epilogue_start_marker ());
2810
4f50b9ff
DD
2811 if (cfun->decl && strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun->decl)), "main") == 0)
2812 emit_insn (gen_msp430_refsym_need_exit ());
2813
a005b5be
NC
2814 if (is_wakeup_func ())
2815 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
2816 status register current residing on the stack. When this function
2817 executes its RETI instruction the SR will be updated with this saved
2818 value, thus ensuring that the processor is woken up from any low power
2819 state in which it may be residing. */
2820 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
2821
f6a83b4a
DD
2822 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
2823
2824 increment_stack (fs);
2825
2826 if (is_eh)
2827 {
2828 /* We need to add the right "SP" register save just after the
2829 regular ones, so that when we pop it off we're in the EH
2830 return frame, not this one. This overwrites our own return
2831 address, but we're not going to be returning anyway. */
2832 rtx r12 = gen_rtx_REG (Pmode, 12);
2833 rtx (*addPmode)(rtx, rtx, rtx) = TARGET_LARGE ? gen_addpsi3 : gen_addhi3;
2834
2835 /* R12 will hold the new SP. */
2836 i = cfun->machine->framesize_regs;
2837 emit_move_insn (r12, stack_pointer_rtx);
2838 emit_insn (addPmode (r12, r12, EH_RETURN_STACKADJ_RTX));
2839 emit_insn (addPmode (r12, r12, GEN_INT (i)));
2840 emit_move_insn (gen_rtx_MEM (Pmode, plus_constant (Pmode, stack_pointer_rtx, i)), r12);
2841 }
2842
2843 for (i = 4; i <= 15; i++)
2844 if (cfun->machine->need_to_save [i])
2845 {
2846 int seq, count;
2847
2848 for (seq = i + 1; seq <= 15 && cfun->machine->need_to_save[seq]; seq ++)
2849 ;
2850 count = seq - i;
2851
2852 if (msp430x)
2853 {
d4f283a1
NC
2854 /* Note: With TARGET_LARGE we still use
2855 POPM as POPX.A is two bytes bigger. */
2856 emit_insn (gen_popm (stack_pointer_rtx, GEN_INT (seq - 1),
f6a83b4a
DD
2857 GEN_INT (count)));
2858 i += count - 1;
2859 }
2860 else if (i == 11 - helper_n
cad055a4
NC
2861 && ! msp430_is_interrupt_func ()
2862 && ! is_reentrant_func ()
2863 && ! is_critical_func ()
f6a83b4a
DD
2864 && crtl->args.pretend_args_size == 0
2865 /* Calling the helper takes as many bytes as the POP;RET sequence. */
40ada30a 2866 && helper_n > 1
f6a83b4a
DD
2867 && !is_eh)
2868 {
2869 emit_insn (gen_epilogue_helper (GEN_INT (helper_n)));
2870 return;
2871 }
2872 else
2873 emit_insn (gen_pop (gen_rtx_REG (Pmode, i)));
2874 }
2875
2876 if (is_eh)
2877 {
2878 /* Also pop SP, which puts us into the EH return frame. Except
2879 that you can't "pop" sp, you have to just load it off the
2880 stack. */
2881 emit_move_insn (stack_pointer_rtx, gen_rtx_MEM (Pmode, stack_pointer_rtx));
2882 }
2883
2884 if (crtl->args.pretend_args_size)
2885 emit_insn (gen_swap_and_shrink ());
cad055a4
NC
2886
2887 if (is_critical_func ())
2888 emit_insn (gen_pop_intr_state ());
2889 else if (is_reentrant_func ())
2890 emit_insn (gen_enable_interrupts ());
2891
f6a83b4a
DD
2892 emit_jump_insn (gen_msp_return ());
2893}
2894
2895/* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
2896 m32c_emit_eh_epilogue. */
2897rtx
2898msp430_eh_return_stackadj_rtx (void)
2899{
2900 if (!cfun->machine->eh_stack_adjust)
2901 {
2902 rtx sa;
2903
2904 sa = gen_rtx_REG (Pmode, 15);
2905 cfun->machine->eh_stack_adjust = sa;
2906 }
2907 return cfun->machine->eh_stack_adjust;
2908}
2909
2910/* This function is called before reload, to "fix" the stack in
2911 preparation for an EH return. */
2912void
2913msp430_expand_eh_return (rtx eh_handler)
2914{
2915 /* These are all Pmode */
2916 rtx ap, sa, ra, tmp;
2917
2918 ap = arg_pointer_rtx;
2919 sa = msp430_eh_return_stackadj_rtx ();
2920 ra = eh_handler;
2921
2922 tmp = ap;
2923 tmp = gen_rtx_PLUS (Pmode, ap, sa);
2924 tmp = plus_constant (Pmode, tmp, TARGET_LARGE ? -4 : -2);
2925 tmp = gen_rtx_MEM (Pmode, tmp);
2926 emit_move_insn (tmp, ra);
2927}
2928
c32ab325
DD
2929#undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
2930#define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
2931void
2932msp430_init_dwarf_reg_sizes_extra (tree address)
2933{
2934 int i;
2935 rtx addr = expand_normal (address);
2936 rtx mem = gen_rtx_MEM (BLKmode, addr);
2937
04a9ae28 2938 /* This needs to match msp430_unwind_word_mode (above). */
c32ab325
DD
2939 if (!msp430x)
2940 return;
2941
2942 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2943 {
2944 unsigned int dnum = DWARF_FRAME_REGNUM (i);
2945 unsigned int rnum = DWARF2_FRAME_REG_OUT (dnum, 1);
2946
2947 if (rnum < DWARF_FRAME_REGISTERS)
2948 {
2949 HOST_WIDE_INT offset = rnum * GET_MODE_SIZE (QImode);
2950
2951 emit_move_insn (adjust_address (mem, QImode, offset),
2952 gen_int_mode (4, QImode));
2953 }
2954 }
2955}
2956
f6a83b4a 2957/* This is a list of MD patterns that implement fixed-count shifts. */
cad055a4
NC
2958static struct
2959{
f6a83b4a
DD
2960 const char *name;
2961 int count;
2962 int need_430x;
2963 rtx (*genfunc)(rtx,rtx);
cad055a4
NC
2964}
2965 const_shift_helpers[] =
2966{
fe1814cf 2967#define CSH(N,C,X,G) { "__mspabi_" N, C, X, gen_##G }
f6a83b4a
DD
2968
2969 CSH ("slli", 1, 1, slli_1),
2970 CSH ("slll", 1, 1, slll_1),
2971 CSH ("slll", 2, 1, slll_2),
2972
2973 CSH ("srai", 1, 0, srai_1),
2974 CSH ("sral", 1, 0, sral_1),
2975 CSH ("sral", 2, 0, sral_2),
2976
2977 CSH ("srll", 1, 0, srll_1),
2978 CSH ("srll", 2, 1, srll_2x),
2979 { 0, 0, 0, 0 }
2980#undef CSH
2981};
2982
2983/* The MSP430 ABI defines a number of helper functions that should be
2984 used for, for example, 32-bit shifts. This function is called to
2985 emit such a function, using the table above to optimize some
2986 cases. */
2987void
2988msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variants)
2989{
2990 rtx c, f;
2991 char *helper_const = NULL;
2992 int arg2 = 13;
2993 int arg1sz = 1;
ef4bddc2
RS
2994 machine_mode arg0mode = GET_MODE (operands[0]);
2995 machine_mode arg1mode = GET_MODE (operands[1]);
2996 machine_mode arg2mode = GET_MODE (operands[2]);
f6a83b4a
DD
2997 int have_430x = msp430x ? 1 : 0;
2998
2999 if (CONST_INT_P (operands[2]))
3000 {
3001 int i;
3002
3003 for (i=0; const_shift_helpers[i].name; i++)
3004 {
3005 if (const_shift_helpers[i].need_430x <= have_430x
3006 && strcmp (helper_name, const_shift_helpers[i].name) == 0
3007 && INTVAL (operands[2]) == const_shift_helpers[i].count)
3008 {
3009 emit_insn (const_shift_helpers[i].genfunc (operands[0], operands[1]));
3010 return;
3011 }
3012 }
3013 }
3014
3015 if (arg1mode == VOIDmode)
3016 arg1mode = arg0mode;
3017 if (arg2mode == VOIDmode)
3018 arg2mode = arg0mode;
3019
3020 if (arg1mode == SImode)
3021 {
3022 arg2 = 14;
3023 arg1sz = 2;
3024 }
3025
3026 if (const_variants
3027 && CONST_INT_P (operands[2])
3028 && INTVAL (operands[2]) >= 1
3029 && INTVAL (operands[2]) <= 15)
3030 {
3031 /* Note that the INTVAL is limited in value and length by the conditional above. */
3032 int len = strlen (helper_name) + 4;
3033 helper_const = (char *) xmalloc (len);
40ada30a 3034 snprintf (helper_const, len, "%s_%d", helper_name, (int) INTVAL (operands[2]));
f6a83b4a
DD
3035 }
3036
3037 emit_move_insn (gen_rtx_REG (arg1mode, 12),
3038 operands[1]);
3039 if (!helper_const)
3040 emit_move_insn (gen_rtx_REG (arg2mode, arg2),
3041 operands[2]);
3042
3043 c = gen_call_value_internal (gen_rtx_REG (arg0mode, 12),
3044 gen_rtx_SYMBOL_REF (VOIDmode, helper_const ? helper_const : helper_name),
3045 GEN_INT (0));
3046 c = emit_call_insn (c);
3047 RTL_CONST_CALL_P (c) = 1;
3048
3049 f = 0;
3050 use_regs (&f, 12, arg1sz);
3051 if (!helper_const)
3052 use_regs (&f, arg2, 1);
3053 add_function_usage_to (c, f);
3054
3055 emit_move_insn (operands[0],
3056 gen_rtx_REG (arg0mode, 12));
3057}
3058
3059/* Called by cbranch<mode>4 to coerce operands into usable forms. */
3060void
ef4bddc2 3061msp430_fixup_compare_operands (machine_mode my_mode, rtx * operands)
f6a83b4a
DD
3062{
3063 /* constants we're looking for, not constants which are allowed. */
3064 int const_op_idx = 1;
3065
3066 if (msp430_reversible_cmp_operator (operands[0], VOIDmode))
3067 const_op_idx = 2;
3068
3069 if (GET_CODE (operands[const_op_idx]) != REG
3070 && GET_CODE (operands[const_op_idx]) != MEM)
3071 operands[const_op_idx] = copy_to_mode_reg (my_mode, operands[const_op_idx]);
3072}
3073
3074/* Simplify_gen_subreg() doesn't handle memory references the way we
3075 need it to below, so we use this function for when we must get a
3076 valid subreg in a "natural" state. */
3077rtx
ef4bddc2 3078msp430_subreg (machine_mode mode, rtx r, machine_mode omode, int byte)
f6a83b4a
DD
3079{
3080 rtx rv;
3081
3082 if (GET_CODE (r) == SUBREG
3083 && SUBREG_BYTE (r) == 0)
3084 {
3085 rtx ireg = SUBREG_REG (r);
ef4bddc2 3086 machine_mode imode = GET_MODE (ireg);
f6a83b4a
DD
3087
3088 /* special case for (HI (SI (PSI ...), 0)) */
3089 if (imode == PSImode
3090 && mode == HImode
3091 && byte == 0)
3092 rv = gen_rtx_SUBREG (mode, ireg, byte);
3093 else
3094 rv = simplify_gen_subreg (mode, ireg, imode, byte);
3095 }
3096 else if (GET_CODE (r) == MEM)
3097 rv = adjust_address (r, mode, byte);
14ae1d88
DD
3098 else if (GET_CODE (r) == SYMBOL_REF
3099 && (byte == 0 || byte == 2)
3100 && mode == HImode)
3101 {
3102 rv = gen_rtx_ZERO_EXTRACT (HImode, r, GEN_INT (16), GEN_INT (8*byte));
3103 rv = gen_rtx_CONST (HImode, r);
3104 }
f6a83b4a
DD
3105 else
3106 rv = simplify_gen_subreg (mode, r, omode, byte);
3107
3108 if (!rv)
3109 gcc_unreachable ();
3110
3111 return rv;
3112}
3113
3114/* Called by movsi_x to generate the HImode operands. */
3115void
3116msp430_split_movsi (rtx *operands)
3117{
3118 rtx op00, op02, op10, op12;
3119
3120 op00 = msp430_subreg (HImode, operands[0], SImode, 0);
3121 op02 = msp430_subreg (HImode, operands[0], SImode, 2);
3122
3123 if (GET_CODE (operands[1]) == CONST
3124 || GET_CODE (operands[1]) == SYMBOL_REF)
3125 {
3126 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
3127 op10 = gen_rtx_CONST (HImode, op10);
3128 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
3129 op12 = gen_rtx_CONST (HImode, op12);
3130 }
3131 else
3132 {
3133 op10 = msp430_subreg (HImode, operands[1], SImode, 0);
3134 op12 = msp430_subreg (HImode, operands[1], SImode, 2);
3135 }
3136
3137 if (rtx_equal_p (operands[0], operands[1]))
3138 {
3139 operands[2] = op02;
3140 operands[4] = op12;
3141 operands[3] = op00;
3142 operands[5] = op10;
3143 }
3144 else if (rtx_equal_p (op00, op12)
3145 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
3146 || (REG_P (op00) && reg_mentioned_p (op00, op10))
3147 /* Or storing (rN) into mem (rN). */
3148 || (REG_P (op10) && reg_mentioned_p (op10, op00))
3149 )
3150 {
3151 operands[2] = op02;
3152 operands[4] = op12;
3153 operands[3] = op00;
3154 operands[5] = op10;
3155 }
3156 else
3157 {
3158 operands[2] = op00;
3159 operands[4] = op10;
3160 operands[3] = op02;
3161 operands[5] = op12;
3162 }
3163}
3164
3165\f
f6a83b4a
DD
3166/* The MSPABI specifies the names of various helper functions, many of
3167 which are compatible with GCC's helpers. This table maps the GCC
3168 name to the MSPABI name. */
3169static const struct
3170{
3171 char const * const gcc_name;
3172 char const * const ti_name;
3173}
3174 helper_function_name_mappings [] =
3175{
3176 /* Floating point to/from integer conversions. */
3177 { "__truncdfsf2", "__mspabi_cvtdf" },
3178 { "__extendsfdf2", "__mspabi_cvtfd" },
3179 { "__fixdfhi", "__mspabi_fixdi" },
3180 { "__fixdfsi", "__mspabi_fixdli" },
3181 { "__fixdfdi", "__mspabi_fixdlli" },
3182 { "__fixunsdfhi", "__mspabi_fixdu" },
3183 { "__fixunsdfsi", "__mspabi_fixdul" },
3184 { "__fixunsdfdi", "__mspabi_fixdull" },
3185 { "__fixsfhi", "__mspabi_fixfi" },
3186 { "__fixsfsi", "__mspabi_fixfli" },
3187 { "__fixsfdi", "__mspabi_fixflli" },
3188 { "__fixunsfhi", "__mspabi_fixfu" },
3189 { "__fixunsfsi", "__mspabi_fixful" },
3190 { "__fixunsfdi", "__mspabi_fixfull" },
3191 { "__floathisf", "__mspabi_fltif" },
3192 { "__floatsisf", "__mspabi_fltlif" },
3193 { "__floatdisf", "__mspabi_fltllif" },
3194 { "__floathidf", "__mspabi_fltid" },
3195 { "__floatsidf", "__mspabi_fltlid" },
3196 { "__floatdidf", "__mspabi_fltllid" },
3197 { "__floatunhisf", "__mspabi_fltuf" },
3198 { "__floatunsisf", "__mspabi_fltulf" },
3199 { "__floatundisf", "__mspabi_fltullf" },
3200 { "__floatunhidf", "__mspabi_fltud" },
3201 { "__floatunsidf", "__mspabi_fltuld" },
3202 { "__floatundidf", "__mspabi_fltulld" },
3203
3204 /* Floating point comparisons. */
3205 /* GCC uses individual functions for each comparison, TI uses one
3206 compare <=> function. */
3207
3208 /* Floating point arithmatic */
3209 { "__adddf3", "__mspabi_addd" },
3210 { "__addsf3", "__mspabi_addf" },
3211 { "__divdf3", "__mspabi_divd" },
3212 { "__divsf3", "__mspabi_divf" },
3213 { "__muldf3", "__mspabi_mpyd" },
3214 { "__mulsf3", "__mspabi_mpyf" },
3215 { "__subdf3", "__mspabi_subd" },
3216 { "__subsf3", "__mspabi_subf" },
3217 /* GCC does not use helper functions for negation */
3218
3219 /* Integer multiply, divide, remainder. */
f6a83b4a
DD
3220 { "__mulhi3", "__mspabi_mpyi" },
3221 { "__mulsi3", "__mspabi_mpyl" },
3222 { "__muldi3", "__mspabi_mpyll" },
3223#if 0
3224 /* Clarify signed vs unsigned first. */
3225 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
3226 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
3227#endif
3228
3229 { "__divhi3", "__mspabi_divi" },
3230 { "__divsi3", "__mspabi_divli" },
3231 { "__divdi3", "__mspabi_divlli" },
3232 { "__udivhi3", "__mspabi_divu" },
04a9ae28
NC
3233 { "__udivsi3", "__mspabi_divul" },
3234 { "__udivdi3", "__mspabi_divull" },
f6a83b4a
DD
3235 { "__modhi3", "__mspabi_remi" },
3236 { "__modsi3", "__mspabi_remli" },
3237 { "__moddi3", "__mspabi_remlli" },
3238 { "__umodhi3", "__mspabi_remu" },
3239 { "__umodsi3", "__mspabi_remul" },
3240 { "__umoddi3", "__mspabi_remull" },
3241
3242 /* Bitwise operations. */
3243 /* Rotation - no rotation support yet. */
3244 /* Logical left shift - gcc already does these itself. */
3245 /* Arithmetic left shift - gcc already does these itself. */
3246 /* Arithmetic right shift - gcc already does these itself. */
3247
3248 { NULL, NULL }
3249};
3250
f642a8b7
NC
3251/* Returns true if the current MCU supports an F5xxx series
3252 hardware multiper. */
3253
c6f709ec 3254bool
f7961364 3255msp430_use_f5_series_hwmult (void)
c6f709ec 3256{
f642a8b7
NC
3257 static const char * cached_match = NULL;
3258 static bool cached_result;
3259
b07447ba 3260 if (msp430_hwmult_type == MSP430_HWMULT_F5SERIES)
f7961364
NC
3261 return true;
3262
b07447ba 3263 if (target_mcu == NULL || msp430_hwmult_type != MSP430_HWMULT_AUTO)
c6f709ec 3264 return false;
f7961364 3265
f642a8b7
NC
3266 if (target_mcu == cached_match)
3267 return cached_result;
3268
3269 cached_match = target_mcu;
3270
3271 if (strncasecmp (target_mcu, "msp430f5", 8) == 0)
3272 return cached_result = true;
6f56da5d
NC
3273 if (strncasecmp (target_mcu, "msp430fr5", 9) == 0)
3274 return cached_result = true;
3275 if (strncasecmp (target_mcu, "msp430f6", 8) == 0)
3276 return cached_result = true;
f642a8b7 3277
f642a8b7
NC
3278 int i;
3279
aad11912
NC
3280 /* FIXME: This array is alpha sorted - we could use a binary search. */
3281 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
3282 if (strcasecmp (target_mcu, msp430_mcu_data[i].name) == 0)
3283 return cached_result = msp430_mcu_data[i].hwmpy == 8;
f642a8b7
NC
3284
3285 return cached_result = false;
c6f709ec
NC
3286}
3287
f642a8b7
NC
3288/* Returns true if the current MCU has a second generation
3289 32-bit hardware multiplier. */
3290
c6f709ec 3291static bool
f7961364 3292use_32bit_hwmult (void)
c6f709ec 3293{
f642a8b7
NC
3294 static const char * cached_match = NULL;
3295 static bool cached_result;
c6f709ec 3296 int i;
f7961364 3297
b07447ba 3298 if (msp430_hwmult_type == MSP430_HWMULT_LARGE)
f7961364
NC
3299 return true;
3300
b07447ba 3301 if (target_mcu == NULL || msp430_hwmult_type != MSP430_HWMULT_AUTO)
c6f709ec
NC
3302 return false;
3303
f642a8b7
NC
3304 if (target_mcu == cached_match)
3305 return cached_result;
3306
3307 cached_match = target_mcu;
aad11912
NC
3308
3309 /* FIXME: This array is alpha sorted - we could use a binary search. */
3310 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
3311 if (strcasecmp (target_mcu, msp430_mcu_data[i].name) == 0)
3312 return cached_result = msp430_mcu_data[i].hwmpy == 4;
c6f709ec 3313
f642a8b7
NC
3314 return cached_result = false;
3315}
3316
3317/* Returns true if the current MCU does not have a
3318 hardware multiplier of any kind. */
3319
3320static bool
3321msp430_no_hwmult (void)
3322{
f642a8b7
NC
3323 static const char * cached_match = NULL;
3324 static bool cached_result;
3325 int i;
3326
b07447ba 3327 if (msp430_hwmult_type == MSP430_HWMULT_NONE)
f642a8b7
NC
3328 return true;
3329
b07447ba 3330 if (msp430_hwmult_type != MSP430_HWMULT_AUTO)
f642a8b7
NC
3331 return false;
3332
04a9ae28
NC
3333 if (target_mcu == NULL)
3334 return true;
3335
f642a8b7
NC
3336 if (target_mcu == cached_match)
3337 return cached_result;
3338
3339 cached_match = target_mcu;
f642a8b7 3340
aad11912
NC
3341 /* FIXME: This array is alpha sorted - we could use a binary search. */
3342 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
3343 if (strcasecmp (target_mcu, msp430_mcu_data[i].name) == 0)
3344 return cached_result = msp430_mcu_data[i].hwmpy == 0;
3345
3346 /* If we do not recognise the MCU name, we assume that it does not support
3347 any kind of hardware multiply - this is the safest assumption to make. */
3348 return cached_result = true;
c6f709ec
NC
3349}
3350
f6a83b4a
DD
3351/* This function does the same as the default, but it will replace GCC
3352 function names with the MSPABI-specified ones. */
f642a8b7 3353
f6a83b4a
DD
3354void
3355msp430_output_labelref (FILE *file, const char *name)
3356{
3357 int i;
3358
3359 for (i = 0; helper_function_name_mappings [i].gcc_name; i++)
c6f709ec 3360 if (strcmp (helper_function_name_mappings [i].gcc_name, name) == 0)
f6a83b4a 3361 {
c6f709ec
NC
3362 name = helper_function_name_mappings [i].ti_name;
3363 break;
f6a83b4a
DD
3364 }
3365
c6f709ec
NC
3366 /* If we have been given a specific MCU name then we may be
3367 able to make use of its hardware multiply capabilities. */
b07447ba 3368 if (msp430_hwmult_type != MSP430_HWMULT_NONE)
c6f709ec
NC
3369 {
3370 if (strcmp ("__mspabi_mpyi", name) == 0)
3371 {
f7961364 3372 if (msp430_use_f5_series_hwmult ())
c6f709ec 3373 name = "__mulhi2_f5";
f642a8b7 3374 else if (! msp430_no_hwmult ())
c6f709ec
NC
3375 name = "__mulhi2";
3376 }
3377 else if (strcmp ("__mspabi_mpyl", name) == 0)
3378 {
f7961364 3379 if (msp430_use_f5_series_hwmult ())
c6f709ec 3380 name = "__mulsi2_f5";
f7961364 3381 else if (use_32bit_hwmult ())
c6f709ec 3382 name = "__mulsi2_hw32";
f642a8b7 3383 else if (! msp430_no_hwmult ())
c6f709ec
NC
3384 name = "__mulsi2";
3385 }
3386 }
3387
f6a83b4a
DD
3388 fputs (name, file);
3389}
3390
40ada30a 3391/* Common code for msp430_print_operand... */
f6a83b4a 3392
f6a83b4a 3393static void
40ada30a 3394msp430_print_operand_raw (FILE * file, rtx op)
f6a83b4a 3395{
a005b5be 3396 HOST_WIDE_INT i;
f6a83b4a
DD
3397
3398 switch (GET_CODE (op))
3399 {
3400 case REG:
3401 fprintf (file, "%s", reg_names [REGNO (op)]);
3402 break;
3403
3404 case CONST_INT:
3405 i = INTVAL (op);
3406 if (TARGET_ASM_HEX)
a005b5be 3407 fprintf (file, "%#" HOST_WIDE_INT_PRINT "x", i);
f6a83b4a 3408 else
a005b5be 3409 fprintf (file, "%" HOST_WIDE_INT_PRINT "d", i);
f6a83b4a
DD
3410 break;
3411
3412 case CONST:
3413 case PLUS:
3414 case MINUS:
3415 case SYMBOL_REF:
3416 case LABEL_REF:
3417 output_addr_const (file, op);
3418 break;
3419
3420 default:
3421 print_rtl (file, op);
3422 break;
3423 }
3424}
3425
40ada30a
NC
3426#undef TARGET_PRINT_OPERAND_ADDRESS
3427#define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
3428
3429/* Output to stdio stream FILE the assembler syntax for an
3430 instruction operand that is a memory reference whose address
3431 is ADDR. */
3432
3433static void
cc8ca59e 3434msp430_print_operand_addr (FILE * file, machine_mode /*mode*/, rtx addr)
40ada30a
NC
3435{
3436 switch (GET_CODE (addr))
3437 {
3438 case PLUS:
3439 msp430_print_operand_raw (file, XEXP (addr, 1));
3440 gcc_assert (REG_P (XEXP (addr, 0)));
3441 fprintf (file, "(%s)", reg_names [REGNO (XEXP (addr, 0))]);
3442 return;
3443
3444 case REG:
3445 fprintf (file, "@");
3446 break;
3447
3448 case CONST:
3449 case CONST_INT:
3450 case SYMBOL_REF:
3451 case LABEL_REF:
3452 fprintf (file, "&");
3453 break;
3454
3455 default:
3456 break;
3457 }
3458
3459 msp430_print_operand_raw (file, addr);
3460}
3461
3462#undef TARGET_PRINT_OPERAND
3463#define TARGET_PRINT_OPERAND msp430_print_operand
3464
51ac3042
NC
3465/* A low 16-bits of int/lower of register pair
3466 B high 16-bits of int/higher of register pair
3467 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
3468 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
3469 H like %B (for backwards compatibility)
3470 I inverse of value
fb28dac0 3471 J an integer without a # prefix
51ac3042
NC
3472 L like %A (for backwards compatibility)
3473 O offset of the top of the stack
3474 Q like X but generates an A postfix
3475 R inverse of condition code, unsigned.
3476 X X instruction postfix in large mode
3477 Y value - 4
3478 Z value - 1
3479 b .B or .W or .A, depending upon the mode
3480 p bit position
3481 r inverse of condition code
3482 x like X but only for pointers. */
3483
f6a83b4a
DD
3484static void
3485msp430_print_operand (FILE * file, rtx op, int letter)
3486{
3487 rtx addr;
3488
3489 /* We can't use c, n, a, or l. */
3490 switch (letter)
3491 {
3492 case 'Z':
3493 gcc_assert (CONST_INT_P (op));
3494 /* Print the constant value, less one. */
3495 fprintf (file, "#%ld", INTVAL (op) - 1);
3496 return;
3497 case 'Y':
3498 gcc_assert (CONST_INT_P (op));
3499 /* Print the constant value, less four. */
3500 fprintf (file, "#%ld", INTVAL (op) - 4);
3501 return;
f6a83b4a
DD
3502 case 'I':
3503 if (GET_CODE (op) == CONST_INT)
3504 {
3505 /* Inverse of constants */
3506 int i = INTVAL (op);
3507 fprintf (file, "%d", ~i);
3508 return;
3509 }
3510 op = XEXP (op, 0);
3511 break;
3512 case 'r': /* Conditional jump where the condition is reversed. */
3513 switch (GET_CODE (op))
3514 {
3515 case EQ: fprintf (file, "NE"); break;
3516 case NE: fprintf (file, "EQ"); break;
3517 case GEU: fprintf (file, "LO"); break;
3518 case LTU: fprintf (file, "HS"); break;
3519 case GE: fprintf (file, "L"); break;
3520 case LT: fprintf (file, "GE"); break;
3521 /* Assume these have reversed operands. */
3522 case GTU: fprintf (file, "HS"); break;
3523 case LEU: fprintf (file, "LO"); break;
3524 case GT: fprintf (file, "GE"); break;
3525 case LE: fprintf (file, "L"); break;
3526 default:
40ada30a 3527 msp430_print_operand_raw (file, op);
f6a83b4a
DD
3528 break;
3529 }
3530 return;
3531 case 'R': /* Conditional jump where the operands are reversed. */
3532 switch (GET_CODE (op))
3533 {
3534 case GTU: fprintf (file, "LO"); break;
3535 case LEU: fprintf (file, "HS"); break;
3536 case GT: fprintf (file, "L"); break;
3537 case LE: fprintf (file, "GE"); break;
3538 default:
40ada30a 3539 msp430_print_operand_raw (file, op);
f6a83b4a
DD
3540 break;
3541 }
3542 return;
3543 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
3544 gcc_assert (CONST_INT_P (op));
3545 fprintf (file, "#%d", 1 << INTVAL (op));
3546 return;
51ac3042 3547 case 'b':
f6a83b4a
DD
3548 switch (GET_MODE (op))
3549 {
4e10a5a7
RS
3550 case E_QImode: fprintf (file, ".B"); return;
3551 case E_HImode: fprintf (file, ".W"); return;
3552 case E_PSImode: fprintf (file, ".A"); return;
3553 case E_SImode: fprintf (file, ".A"); return;
f6a83b4a
DD
3554 default:
3555 return;
3556 }
51ac3042 3557 case 'A':
f6a83b4a
DD
3558 case 'L': /* Low half. */
3559 switch (GET_CODE (op))
3560 {
3561 case MEM:
3562 op = adjust_address (op, Pmode, 0);
3563 break;
3564 case REG:
3565 break;
3566 case CONST_INT:
3567 op = GEN_INT (INTVAL (op) & 0xffff);
3568 letter = 0;
3569 break;
3570 default:
3571 /* If you get here, figure out a test case :-) */
3572 gcc_unreachable ();
3573 }
3574 break;
51ac3042 3575 case 'B':
f6a83b4a
DD
3576 case 'H': /* high half */
3577 switch (GET_CODE (op))
3578 {
3579 case MEM:
3580 op = adjust_address (op, Pmode, 2);
3581 break;
3582 case REG:
3583 op = gen_rtx_REG (Pmode, REGNO (op) + 1);
3584 break;
3585 case CONST_INT:
3586 op = GEN_INT (INTVAL (op) >> 16);
3587 letter = 0;
3588 break;
3589 default:
3590 /* If you get here, figure out a test case :-) */
3591 gcc_unreachable ();
3592 }
3593 break;
51ac3042
NC
3594 case 'C':
3595 switch (GET_CODE (op))
3596 {
3597 case MEM:
3598 op = adjust_address (op, Pmode, 3);
3599 break;
3600 case REG:
3601 op = gen_rtx_REG (Pmode, REGNO (op) + 2);
3602 break;
3603 case CONST_INT:
c6f709ec 3604 op = GEN_INT ((long long) INTVAL (op) >> 32);
51ac3042
NC
3605 letter = 0;
3606 break;
3607 default:
3608 /* If you get here, figure out a test case :-) */
3609 gcc_unreachable ();
3610 }
3611 break;
3612 case 'D':
3613 switch (GET_CODE (op))
3614 {
3615 case MEM:
3616 op = adjust_address (op, Pmode, 4);
3617 break;
3618 case REG:
3619 op = gen_rtx_REG (Pmode, REGNO (op) + 3);
3620 break;
3621 case CONST_INT:
c6f709ec 3622 op = GEN_INT ((long long) INTVAL (op) >> 48);
51ac3042
NC
3623 letter = 0;
3624 break;
3625 default:
3626 /* If you get here, figure out a test case :-) */
3627 gcc_unreachable ();
3628 }
3629 break;
f6a83b4a
DD
3630
3631 case 'X':
3632 /* This is used to turn, for example, an ADD opcode into an ADDX
3633 opcode when we're using 20-bit addresses. */
c32ab325 3634 if (TARGET_LARGE || GET_MODE (op) == PSImode)
f6a83b4a
DD
3635 fprintf (file, "X");
3636 /* We don't care which operand we use, but we want 'X' in the MD
3637 file, so we do it this way. */
3638 return;
3639
3640 case 'x':
3641 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
5cbc4e2a 3642 if (GET_MODE (op) == PSImode)
f6a83b4a
DD
3643 fprintf (file, "X");
3644 return;
3645
51ac3042 3646 case 'Q':
f6a83b4a
DD
3647 /* Likewise, for BR -> BRA. */
3648 if (TARGET_LARGE)
3649 fprintf (file, "A");
3650 return;
cad055a4
NC
3651
3652 case 'O':
3653 /* Computes the offset to the top of the stack for the current frame.
3654 This has to be done here rather than in, say, msp430_expand_builtin()
3655 because builtins are expanded before the frame layout is determined. */
3656 fprintf (file, "%d",
3657 msp430_initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM)
d77f7b19 3658 - (TARGET_LARGE ? 4 : 2));
40ada30a 3659 return;
51ac3042 3660
fb28dac0
DD
3661 case 'J':
3662 gcc_assert (GET_CODE (op) == CONST_INT);
51ac3042
NC
3663 case 0:
3664 break;
3665 default:
3666 output_operand_lossage ("invalid operand prefix");
3667 return;
f6a83b4a
DD
3668 }
3669
3670 switch (GET_CODE (op))
3671 {
3672 case REG:
40ada30a 3673 msp430_print_operand_raw (file, op);
f6a83b4a
DD
3674 break;
3675
3676 case MEM:
3677 addr = XEXP (op, 0);
cc8ca59e 3678 msp430_print_operand_addr (file, GET_MODE (op), addr);
f6a83b4a
DD
3679 break;
3680
f6a83b4a 3681 case CONST:
467fc67c
NC
3682 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTRACT)
3683 {
3684 op = XEXP (op, 0);
3685 switch (INTVAL (XEXP (op, 2)))
3686 {
3687 case 0:
3688 fprintf (file, "#lo (");
3689 msp430_print_operand_raw (file, XEXP (op, 0));
3690 fprintf (file, ")");
3691 break;
3692
3693 case 16:
3694 fprintf (file, "#hi (");
3695 msp430_print_operand_raw (file, XEXP (op, 0));
3696 fprintf (file, ")");
3697 break;
3698
3699 default:
3700 output_operand_lossage ("invalid zero extract");
3701 break;
3702 }
3703 break;
3704 }
3705 /* Fall through. */
3706 case CONST_INT:
f6a83b4a
DD
3707 case SYMBOL_REF:
3708 case LABEL_REF:
3709 if (letter == 0)
3710 fprintf (file, "#");
40ada30a 3711 msp430_print_operand_raw (file, op);
f6a83b4a
DD
3712 break;
3713
3714 case EQ: fprintf (file, "EQ"); break;
3715 case NE: fprintf (file, "NE"); break;
3716 case GEU: fprintf (file, "HS"); break;
3717 case LTU: fprintf (file, "LO"); break;
3718 case GE: fprintf (file, "GE"); break;
3719 case LT: fprintf (file, "L"); break;
3720
3721 default:
3722 print_rtl (file, op);
3723 break;
3724 }
f6a83b4a
DD
3725}
3726
3727\f
3728/* Frame stuff. */
3729
3730rtx
3731msp430_return_addr_rtx (int count)
3732{
3733 int ra_size;
3734 if (count)
3735 return NULL_RTX;
3736
3737 ra_size = TARGET_LARGE ? 4 : 2;
3738 if (crtl->args.pretend_args_size)
3739 ra_size += 2;
3740
3741 return gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, arg_pointer_rtx, GEN_INT (- ra_size)));
3742}
3743
3744rtx
3745msp430_incoming_return_addr_rtx (void)
3746{
3747 return gen_rtx_MEM (Pmode, stack_pointer_rtx);
3748}
3749\f
3750/* Instruction generation stuff. */
3751
3752/* Generate a sequence of instructions to sign-extend an HI
3753 value into an SI value. Handles the tricky case where
3754 we are overwriting the destination. */
3755
3756const char *
3757msp430x_extendhisi (rtx * operands)
3758{
3759 if (REGNO (operands[0]) == REGNO (operands[1]))
3760 /* Low word of dest == source word. */
d4f283a1 3761 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
f6a83b4a
DD
3762
3763 if (! msp430x)
3764 /* Note: This sequence is approximately the same length as invoking a helper
3765 function to perform the sign-extension, as in:
c6f709ec 3766
f6a83b4a
DD
3767 MOV.W %1, %L0
3768 MOV.W %1, r12
3769 CALL __mspabi_srai_15
3770 MOV.W r12, %H0
3771
3772 but this version does not involve any function calls or using argument
3773 registers, so it reduces register pressure. */
d4f283a1 3774 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
c6f709ec 3775
f6a83b4a
DD
3776 if (REGNO (operands[0]) + 1 == REGNO (operands[1]))
3777 /* High word of dest == source word. */
d4f283a1 3778 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
f6a83b4a
DD
3779
3780 /* No overlap between dest and source. */
d4f283a1 3781 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
f6a83b4a
DD
3782}
3783
3784/* Likewise for logical right shifts. */
3785const char *
3786msp430x_logical_shift_right (rtx amount)
3787{
3788 /* The MSP430X's logical right shift instruction - RRUM - does
3789 not use an extension word, so we cannot encode a repeat count.
3790 Try various alternatives to work around this. If the count
3791 is in a register we are stuck, hence the assert. */
3792 gcc_assert (CONST_INT_P (amount));
3793
3794 if (INTVAL (amount) <= 0
3795 || INTVAL (amount) >= 16)
3796 return "# nop logical shift.";
3797
c6f709ec 3798 if (INTVAL (amount) > 0
f6a83b4a
DD
3799 && INTVAL (amount) < 5)
3800 return "rrum.w\t%2, %0"; /* Two bytes. */
3801
c6f709ec 3802 if (INTVAL (amount) > 4
f6a83b4a
DD
3803 && INTVAL (amount) < 9)
3804 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
3805
3806 /* First we logically shift right by one. Now we know
3807 that the top bit is zero and we can use the arithmetic
3808 right shift instruction to perform the rest of the shift. */
3809 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
3810}
3811\f
3812struct gcc_target targetm = TARGET_INITIALIZER;
3813
3814#include "gt-msp430.h"