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