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