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