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