1 /* Subroutines used for code generation on TI MSP430 processors.
2    Copyright (C) 2012-2014 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 "tm.h"
25 #include "tree.h"
26 #include "stor-layout.h"
27 #include "calls.h"
28 #include "rtl.h"
29 #include "regs.h"
30 #include "hard-reg-set.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "output.h"
34 #include "insn-attr.h"
35 #include "flags.h"
36 #include "function.h"
37 #include "expr.h"
38 #include "optabs.h"
39 #include "libfuncs.h"
40 #include "recog.h"
41 #include "diagnostic-core.h"
42 #include "toplev.h"
43 #include "reload.h"
44 #include "df.h"
45 #include "ggc.h"
46 #include "tm_p.h"
47 #include "debug.h"
48 #include "target.h"
49 #include "target-def.h"
50 #include "langhooks.h"
51 #include "msp430-protos.h"
52 #include "dumpfile.h"
53 #include "opts.h"
54 
55 
56 static void msp430_compute_frame_info (void);
57 
58 
59 
60 /* Run-time Target Specification.  */
61 
62 bool msp430x = true;
63 
64 struct GTY(()) machine_function
65 {
66   /* If set, the rest of the fields have been computed.  */
67   int computed;
68   /* Which registers need to be saved in the pro/epilogue.  */
69   int need_to_save [FIRST_PSEUDO_REGISTER];
70 
71   /* These fields describe the frame layout...  */
72   /* arg pointer */
73   /* 2/4 bytes for saved PC */
74   int framesize_regs;
75   /* frame pointer */
76   int framesize_locals;
77   int framesize_outgoing;
78   /* stack pointer */
79   int framesize;
80 
81   /* How much we adjust the stack when returning from an exception
82      handler.  */
83   rtx eh_stack_adjust;
84 };
85 
86 /* This is our init_machine_status, as set in
87    msp_option_override.  */
88 static struct machine_function *
msp430_init_machine_status(void)89 msp430_init_machine_status (void)
90 {
91   struct machine_function *m;
92 
93   m = ggc_alloc_cleared_machine_function ();
94 
95   return m;
96 }
97 
98 #undef  TARGET_OPTION_OVERRIDE
99 #define TARGET_OPTION_OVERRIDE		msp430_option_override
100 
101 static const char * msp430_mcu_names [] =
102 {
103 "msp430afe221",	"msp430afe222",	"msp430afe223",	"msp430afe231",
104 "msp430afe232",	"msp430afe233",	"msp430afe251",	"msp430afe252",
105 "msp430afe253",	"msp430c091",	"msp430c092",	"msp430c111",
106 "msp430c1111",	"msp430c112",	"msp430c1121",	"msp430c1331",
107 "msp430c1351",	"msp430c311s",	"msp430c312",	"msp430c313",
108 "msp430c314",	"msp430c315",	"msp430c323",	"msp430c325",
109 "msp430c336",	"msp430c337",	"msp430c412",	"msp430c413",
110 "msp430e112",	"msp430e313",	"msp430e315",	"msp430e325",
111 "msp430e337",	"msp430f110",	"msp430f1101",	"msp430f1101a",
112 "msp430f1111",	"msp430f1111a",	"msp430f112",	"msp430f1121",
113 "msp430f1121a",	"msp430f1122",	"msp430f1132",	"msp430f122",
114 "msp430f1222",	"msp430f123",	"msp430f1232",	"msp430f133",
115 "msp430f135",	"msp430f147",	"msp430f1471",	"msp430f148",
116 "msp430f1481",	"msp430f149",	"msp430f1491",	"msp430f155",
117 "msp430f156",	"msp430f157",	"msp430f1610",	"msp430f1611",
118 "msp430f1612",	"msp430f167",	"msp430f168",	"msp430f169",
119 "msp430f2001",	"msp430f2002",	"msp430f2003",	"msp430f2011",
120 "msp430f2012",	"msp430f2013",	"msp430f2101",	"msp430f2111",
121 "msp430f2112",	"msp430f2121",	"msp430f2122",	"msp430f2131",
122 "msp430f2132",	"msp430f2232",	"msp430f2234",	"msp430f2252",
123 "msp430f2254",	"msp430f2272",	"msp430f2274",	"msp430f233",
124 "msp430f2330",	"msp430f235",	"msp430f2350",	"msp430f2370",
125 "msp430f2410",	"msp430f247",	"msp430f2471",	"msp430f248",
126 "msp430f2481",	"msp430f249",	"msp430f2491",	"msp430f412",
127 "msp430f413",	"msp430f4132",	"msp430f415",	"msp430f4152",
128 "msp430f417",	"msp430f423",	"msp430f423a",	"msp430f425",
129 "msp430f4250",	"msp430f425a",	"msp430f4260",	"msp430f427",
130 "msp430f4270",	"msp430f427a",	"msp430f435",	"msp430f4351",
131 "msp430f436",	"msp430f4361",	"msp430f437",	"msp430f4371",
132 "msp430f438",	"msp430f439",	"msp430f447",	"msp430f448",
133 "msp430f4481",	"msp430f449",	"msp430f4491",	"msp430f477",
134 "msp430f478",	"msp430f4783",	"msp430f4784",	"msp430f479",
135 "msp430f4793",	"msp430f4794",	"msp430fe423",	"msp430fe4232",
136 "msp430fe423a",	"msp430fe4242",	"msp430fe425",	"msp430fe4252",
137 "msp430fe425a",	"msp430fe427",	"msp430fe4272",	"msp430fe427a",
138 "msp430fg4250",	"msp430fg4260",	"msp430fg4270",	"msp430fg437",
139 "msp430fg438",	"msp430fg439",	"msp430fg477",	"msp430fg478",
140 "msp430fg479",	"msp430fw423",	"msp430fw425",	"msp430fw427",
141 "msp430fw428",	"msp430fw429",	"msp430g2001",	"msp430g2101",
142 "msp430g2102",	"msp430g2111",	"msp430g2112",	"msp430g2113",
143 "msp430g2121",	"msp430g2131",	"msp430g2132",	"msp430g2152",
144 "msp430g2153",	"msp430g2201",	"msp430g2202",	"msp430g2203",
145 "msp430g2210",	"msp430g2211",	"msp430g2212",	"msp430g2213",
146 "msp430g2221",	"msp430g2230",	"msp430g2231",	"msp430g2232",
147 "msp430g2233",	"msp430g2252",	"msp430g2253",	"msp430g2302",
148 "msp430g2303",	"msp430g2312",	"msp430g2313",	"msp430g2332",
149 "msp430g2333",	"msp430g2352",	"msp430g2353",	"msp430g2402",
150 "msp430g2403",	"msp430g2412",	"msp430g2413",	"msp430g2432",
151 "msp430g2433",	"msp430g2444",	"msp430g2452",	"msp430g2453",
152 "msp430g2513",	"msp430g2533",	"msp430g2544",	"msp430g2553",
153 "msp430g2744",	"msp430g2755",	"msp430g2855",	"msp430g2955",
154 "msp430i2020",	"msp430i2021",	"msp430i2030",	"msp430i2031",
155 "msp430i2040",	"msp430i2041",	"msp430l092",   "msp430p112",
156 "msp430p313",	"msp430p315",	"msp430p315s",	"msp430p325",
157 "msp430p337",	"msp430tch5e"
158 };
159 
160 /* Generate a C preprocessor symbol based upon the MCU selected by the user.
161    If a specific MCU has not been selected then return a generic symbol instead.  */
162 
163 const char *
msp430_mcu_name(void)164 msp430_mcu_name (void)
165 {
166   if (target_mcu)
167     {
168       unsigned int i;
169       static char mcu_name [64];
170 
171       snprintf (mcu_name, sizeof (mcu_name) - 1, "__%s__", target_mcu);
172       for (i = strlen (mcu_name); i--;)
173 	mcu_name[i] = TOUPPER (mcu_name[i]);
174       return mcu_name;
175     }
176 
177   return msp430x ? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
178 }
179 
180 static void
msp430_option_override(void)181 msp430_option_override (void)
182 {
183   init_machine_status = msp430_init_machine_status;
184 
185   if (target_cpu)
186     {
187       if (strcasecmp (target_cpu, "msp430x") == 0)
188 	msp430x = true;
189       else /* target_cpu == "msp430" - already handled by the front end.  */
190 	msp430x = false;
191     }
192   /* Note - the front end has already ensured at most
193      one of target_cpu and target_mcu will be set.  */
194   else if (target_mcu)
195     {
196       int i;
197 
198       /* If we are given an MCU name, we assume that it supports 430X.
199 	 Then we check to see if it is one of the known MCUs that only
200 	 supports 430.  */
201       msp430x = true;
202 
203       for (i = ARRAY_SIZE (msp430_mcu_names); i--;)
204 	if (strcasecmp (msp430_mcu_names[i], target_mcu) == 0)
205 	  {
206 	    msp430x = false;
207 	    break;
208 	  }
209       /* It is not an error if we do not match the MCU name.  There are
210 	 hundreds of them.  */
211     }
212 
213   if (TARGET_LARGE && !msp430x)
214     error ("-mlarge requires a 430X-compatible -mmcu=");
215 
216   if (flag_exceptions || flag_non_call_exceptions
217       || flag_unwind_tables || flag_asynchronous_unwind_tables)
218     flag_omit_frame_pointer = false;
219   else
220     flag_omit_frame_pointer = true;
221 
222   /* This is a hack to work around a problem with the newlib build
223      mechanism.  Newlib always appends CFLAGS to the end of the GCC
224      command line and always sets -O2 in CFLAGS.  Thus it is not
225      possible to build newlib with -Os enabled.  Until now...  */
226   if (TARGET_OPT_SPACE && optimize < 3)
227     optimize_size = 1;
228 }
229 
230 
231 
232 /* Storage Layout */
233 
234 #undef  TARGET_MS_BITFIELD_LAYOUT_P
235 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
236 
237 bool
msp430_ms_bitfield_layout_p(const_tree record_type ATTRIBUTE_UNUSED)238 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED)
239 {
240   return false;
241 }
242 
243 
244 
245 /* Register Usage */
246 
247 /* Implements HARD_REGNO_NREGS.  MSP430X registers can hold a single
248    PSImode value, but not an SImode value.  */
249 int
msp430_hard_regno_nregs(int regno ATTRIBUTE_UNUSED,enum machine_mode mode)250 msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED,
251 			 enum machine_mode mode)
252 {
253   if (mode == PSImode && msp430x)
254     return 1;
255   return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
256 	  / UNITS_PER_WORD);
257 }
258 
259 /* Implements HARD_REGNO_MODE_OK.  */
260 int
msp430_hard_regno_mode_ok(int regno ATTRIBUTE_UNUSED,enum machine_mode mode)261 msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED,
262 			   enum machine_mode mode)
263 {
264   return regno <= (ARG_POINTER_REGNUM - msp430_hard_regno_nregs (regno, mode));
265 }
266 
267 /* Implements MODES_TIEABLE_P.  */
268 bool
msp430_modes_tieable_p(enum machine_mode mode1,enum machine_mode mode2)269 msp430_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
270 {
271   if ((mode1 == PSImode || mode2 == SImode)
272       || (mode1 == SImode || mode2 == PSImode))
273     return false;
274 
275   return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
276 	   || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
277 	  == (GET_MODE_CLASS (mode2) == MODE_FLOAT
278 	      || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
279 }
280 
281 #undef  TARGET_FRAME_POINTER_REQUIRED
282 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
283 
284 static bool
msp430_frame_pointer_required(void)285 msp430_frame_pointer_required (void)
286 {
287   return false;
288 }
289 
290 #undef  TARGET_CAN_ELIMINATE
291 #define TARGET_CAN_ELIMINATE		msp430_can_eliminate
292 
293 static bool
msp430_can_eliminate(const int from_reg ATTRIBUTE_UNUSED,const int to_reg ATTRIBUTE_UNUSED)294 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED,
295 		      const int to_reg ATTRIBUTE_UNUSED)
296 {
297   return true;
298 }
299 
300 /* Implements INITIAL_ELIMINATION_OFFSET.  */
301 int
msp430_initial_elimination_offset(int from,int to)302 msp430_initial_elimination_offset (int from, int to)
303 {
304   int rv = 0; /* As if arg to arg.  */
305 
306   msp430_compute_frame_info ();
307 
308   switch (to)
309     {
310     case STACK_POINTER_REGNUM:
311       rv += cfun->machine->framesize_outgoing;
312       rv += cfun->machine->framesize_locals;
313       /* Fall through.  */
314     case FRAME_POINTER_REGNUM:
315       rv += cfun->machine->framesize_regs;
316       /* Allow for the saved return address.  */
317       rv += (TARGET_LARGE ? 4 : 2);
318       /* NB/ No need to allow for crtl->args.pretend_args_size.
319          GCC does that for us.  */
320       break;
321     default:
322       gcc_unreachable ();
323     }
324 
325   switch (from)
326     {
327     case FRAME_POINTER_REGNUM:
328       /* Allow for the fall through above.  */
329       rv -= (TARGET_LARGE ? 4 : 2);
330       rv -= cfun->machine->framesize_regs;
331     case ARG_POINTER_REGNUM:
332       break;
333     default:
334       gcc_unreachable ();
335     }
336 
337   return rv;
338 }
339 
340 /* Named Address Space support */
341 
342 
343 /* Return the appropriate mode for a named address pointer.  */
344 #undef  TARGET_ADDR_SPACE_POINTER_MODE
345 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
346 #undef  TARGET_ADDR_SPACE_ADDRESS_MODE
347 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
348 
349 static enum machine_mode
msp430_addr_space_pointer_mode(addr_space_t addrspace)350 msp430_addr_space_pointer_mode (addr_space_t addrspace)
351 {
352   switch (addrspace)
353     {
354     default:
355     case ADDR_SPACE_GENERIC:
356       return Pmode;
357     case ADDR_SPACE_NEAR:
358       return HImode;
359     case ADDR_SPACE_FAR:
360       return PSImode;
361     }
362 }
363 
364 /* Function pointers are stored in unwind_word sized
365    variables, so make sure that unwind_word is big enough.  */
366 #undef  TARGET_UNWIND_WORD_MODE
367 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
368 
369 static enum machine_mode
msp430_unwind_word_mode(void)370 msp430_unwind_word_mode (void)
371 {
372   return TARGET_LARGE ? SImode : HImode;
373 }
374 
375 /* Determine if one named address space is a subset of another.  */
376 #undef  TARGET_ADDR_SPACE_SUBSET_P
377 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
378 static bool
msp430_addr_space_subset_p(addr_space_t subset,addr_space_t superset)379 msp430_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
380 {
381   if (subset == superset)
382     return true;
383   else
384     return (subset != ADDR_SPACE_FAR && superset == ADDR_SPACE_FAR);
385 }
386 
387 #undef  TARGET_ADDR_SPACE_CONVERT
388 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
389 /* Convert from one address space to another.  */
390 static rtx
msp430_addr_space_convert(rtx op,tree from_type,tree to_type)391 msp430_addr_space_convert (rtx op, tree from_type, tree to_type)
392 {
393   addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
394   addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
395   rtx result;
396 
397   if (to_as != ADDR_SPACE_FAR && from_as == ADDR_SPACE_FAR)
398     {
399       /* This is unpredictable, as we're truncating off usable address
400 	 bits.  */
401 
402       if (CONSTANT_P (op))
403 	return gen_rtx_CONST (HImode, op);
404 
405       result = gen_reg_rtx (HImode);
406       emit_insn (gen_truncpsihi2 (result, op));
407       return result;
408     }
409   else if (to_as == ADDR_SPACE_FAR && from_as != ADDR_SPACE_FAR)
410     {
411       /* This always works.  */
412 
413       if (CONSTANT_P (op))
414 	return gen_rtx_CONST (PSImode, op);
415 
416       result = gen_reg_rtx (PSImode);
417       emit_insn (gen_zero_extendhipsi2 (result, op));
418       return result;
419     }
420   else
421     gcc_unreachable ();
422 }
423 
424 /* Stack Layout and Calling Conventions.  */
425 
426 /* For each function, we list the gcc version and the TI version on
427    each line, where we're converting the function names.  */
428 static char const * const special_convention_function_names [] =
429 {
430   "__muldi3", "__mspabi_mpyll",
431   "__udivdi3", "__mspabi_divull",
432   "__umoddi3", "__mspabi_remull",
433   "__divdi3", "__mspabi_divlli",
434   "__moddi3", "__mspabi_remlli",
435   "__mspabi_srall",
436   "__mspabi_srlll",
437   "__mspabi_sllll",
438   "__adddf3", "__mspabi_addd",
439   "__subdf3", "__mspabi_subd",
440   "__muldf3", "__mspabi_mpyd",
441   "__divdf3", "__mspabi_divd",
442   "__mspabi_cmpd",
443   NULL
444 };
445 
446 /* TRUE if the function passed is a "speical" function.  Special
447    functions pass two DImode parameters in registers.  */
448 static bool
msp430_special_register_convention_p(const char * name)449 msp430_special_register_convention_p (const char *name)
450 {
451   int i;
452 
453   for (i = 0; special_convention_function_names [i]; i++)
454     if (! strcmp (name, special_convention_function_names [i]))
455       return true;
456 
457   return false;
458 }
459 
460 #undef  TARGET_FUNCTION_VALUE_REGNO_P
461 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
462 
463 bool
msp430_function_value_regno_p(unsigned int regno)464 msp430_function_value_regno_p (unsigned int regno)
465 {
466   return regno == 12;
467 }
468 
469 
470 #undef  TARGET_FUNCTION_VALUE
471 #define TARGET_FUNCTION_VALUE msp430_function_value
472 
473 rtx
msp430_function_value(const_tree ret_type,const_tree fn_decl_or_type ATTRIBUTE_UNUSED,bool outgoing ATTRIBUTE_UNUSED)474 msp430_function_value (const_tree ret_type,
475 		       const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
476 		       bool outgoing ATTRIBUTE_UNUSED)
477 {
478   return gen_rtx_REG (TYPE_MODE (ret_type), 12);
479 }
480 
481 #undef  TARGET_LIBCALL_VALUE
482 #define TARGET_LIBCALL_VALUE msp430_libcall_value
483 
484 rtx
msp430_libcall_value(enum machine_mode mode,const_rtx fun ATTRIBUTE_UNUSED)485 msp430_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
486 {
487   return gen_rtx_REG (mode, 12);
488 }
489 
490 /* Implements INIT_CUMULATIVE_ARGS.  */
491 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)492 msp430_init_cumulative_args (CUMULATIVE_ARGS *ca,
493 			     tree fntype ATTRIBUTE_UNUSED,
494 			     rtx libname ATTRIBUTE_UNUSED,
495 			     tree fndecl ATTRIBUTE_UNUSED,
496 			     int n_named_args ATTRIBUTE_UNUSED)
497 {
498   const char *fname;
499   memset (ca, 0, sizeof(*ca));
500 
501   ca->can_split = 1;
502 
503   if (fndecl)
504     fname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
505   else if (libname)
506     fname = XSTR (libname, 0);
507   else
508     fname = NULL;
509 
510   if (fname && msp430_special_register_convention_p (fname))
511     ca->special_p = 1;
512 }
513 
514 /* Helper function for argument passing; this function is the common
515    code that determines where an argument will be passed.  */
516 static void
msp430_evaluate_arg(cumulative_args_t cap,enum machine_mode mode,const_tree type ATTRIBUTE_UNUSED,bool named)517 msp430_evaluate_arg (cumulative_args_t cap,
518 		     enum machine_mode mode,
519 		     const_tree type ATTRIBUTE_UNUSED,
520 		     bool named)
521 {
522   CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
523   int nregs = GET_MODE_SIZE (mode);
524   int i;
525 
526   ca->reg_count = 0;
527   ca->mem_count = 0;
528 
529   if (!named)
530     return;
531 
532   if (mode == PSImode)
533     nregs = 1;
534   else
535     nregs = (nregs + 1) / 2;
536 
537   if (ca->special_p)
538     {
539       /* Function is passed two DImode operands, in R8:R11 and
540 	 R12:15.  */
541       ca->start_reg = 8;
542       ca->reg_count = 4;
543       return;
544     }
545 
546   switch (nregs)
547     {
548     case 1:
549       for (i = 0; i < 4; i++)
550 	if (! ca->reg_used [i])
551 	  {
552 	    ca->reg_count = 1;
553 	    ca->start_reg = CA_FIRST_REG + i;
554 	    return;
555 	  }
556       break;
557     case 2:
558       for (i = 0; i < 3; i++)
559 	if (! ca->reg_used [i] && ! ca->reg_used [i + 1])
560 	  {
561 	    ca->reg_count = 2;
562 	    ca->start_reg = CA_FIRST_REG + i;
563 	    return;
564 	  }
565       if (! ca->reg_used [3] && ca->can_split)
566 	{
567 	  ca->reg_count = 1;
568 	  ca->mem_count = 2;
569 	  ca->start_reg = CA_FIRST_REG + 3;
570 	  return;
571 	}
572       break;
573     case 3:
574     case 4:
575       ca->can_split = 0;
576       if (! ca->reg_used [0]
577 	  && ! ca->reg_used [1]
578 	  && ! ca->reg_used [2]
579 	  && ! ca->reg_used [3])
580 	{
581 	  ca->reg_count = 4;
582 	  ca->start_reg = CA_FIRST_REG;
583 	  return;
584 	}
585       break;
586     }
587 }
588 
589 #undef  TARGET_PROMOTE_PROTOTYPES
590 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
591 
592 bool
msp430_promote_prototypes(const_tree fntype ATTRIBUTE_UNUSED)593 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED)
594 {
595   return false;
596 }
597 
598 #undef  TARGET_FUNCTION_ARG
599 #define TARGET_FUNCTION_ARG msp430_function_arg
600 
601 rtx
msp430_function_arg(cumulative_args_t cap,enum machine_mode mode,const_tree type,bool named)602 msp430_function_arg (cumulative_args_t cap,
603 		     enum machine_mode mode,
604 		     const_tree type,
605 		     bool named)
606 {
607   CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
608 
609   msp430_evaluate_arg (cap, mode, type, named);
610 
611   if (ca->reg_count)
612     return gen_rtx_REG (mode, ca->start_reg);
613 
614   return 0;
615 }
616 
617 #undef  TARGET_ARG_PARTIAL_BYTES
618 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
619 
620 int
msp430_arg_partial_bytes(cumulative_args_t cap,enum machine_mode mode,tree type,bool named)621 msp430_arg_partial_bytes (cumulative_args_t cap,
622 			  enum machine_mode mode,
623 			  tree type,
624 			  bool named)
625 {
626   CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
627 
628   msp430_evaluate_arg (cap, mode, type, named);
629 
630   if (ca->reg_count && ca->mem_count)
631     return ca->reg_count * UNITS_PER_WORD;
632 
633   return 0;
634 }
635 
636 #undef  TARGET_PASS_BY_REFERENCE
637 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
638 
639 static bool
msp430_pass_by_reference(cumulative_args_t cap ATTRIBUTE_UNUSED,enum machine_mode mode,const_tree type,bool named ATTRIBUTE_UNUSED)640 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED,
641 			  enum machine_mode mode,
642 			  const_tree type,
643 			  bool named ATTRIBUTE_UNUSED)
644 {
645   return (mode == BLKmode
646 	  || (type && TREE_CODE (type) == RECORD_TYPE)
647 	  || (type && TREE_CODE (type) == UNION_TYPE));
648 }
649 
650 #undef  TARGET_CALLEE_COPIES
651 #define TARGET_CALLEE_COPIES msp430_callee_copies
652 
653 static bool
msp430_callee_copies(cumulative_args_t cap ATTRIBUTE_UNUSED,enum machine_mode mode ATTRIBUTE_UNUSED,const_tree type ATTRIBUTE_UNUSED,bool named ATTRIBUTE_UNUSED)654 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED,
655                      enum machine_mode mode ATTRIBUTE_UNUSED,
656                      const_tree type ATTRIBUTE_UNUSED,
657                      bool named ATTRIBUTE_UNUSED)
658 {
659   return true;
660 }
661 
662 #undef  TARGET_FUNCTION_ARG_ADVANCE
663 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
664 
665 void
msp430_function_arg_advance(cumulative_args_t cap,enum machine_mode mode,const_tree type,bool named)666 msp430_function_arg_advance (cumulative_args_t cap,
667 			     enum machine_mode mode,
668 			     const_tree type,
669 			     bool named)
670 {
671   CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
672   int i;
673 
674   msp430_evaluate_arg (cap, mode, type, named);
675 
676   if (ca->start_reg >= CA_FIRST_REG)
677     for (i = 0; i < ca->reg_count; i ++)
678       ca->reg_used [i + ca->start_reg - CA_FIRST_REG] = 1;
679 
680   ca->special_p = 0;
681 }
682 
683 #undef  TARGET_FUNCTION_ARG_BOUNDARY
684 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
685 
686 static unsigned int
msp430_function_arg_boundary(enum machine_mode mode,const_tree type)687 msp430_function_arg_boundary (enum machine_mode mode, const_tree type)
688 {
689   if (mode == BLKmode
690       && int_size_in_bytes (type) > 1)
691     return 16;
692   if (GET_MODE_BITSIZE (mode) > 8)
693     return 16;
694   return 8;
695 }
696 
697 #undef  TARGET_RETURN_IN_MEMORY
698 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
699 
700 static bool
msp430_return_in_memory(const_tree ret_type,const_tree fntype ATTRIBUTE_UNUSED)701 msp430_return_in_memory (const_tree ret_type, const_tree fntype ATTRIBUTE_UNUSED)
702 {
703   enum machine_mode mode = TYPE_MODE (ret_type);
704 
705   if (mode == BLKmode
706       || (fntype && TREE_CODE (TREE_TYPE (fntype)) == RECORD_TYPE)
707       || (fntype && TREE_CODE (TREE_TYPE (fntype)) == UNION_TYPE))
708     return true;
709 
710   if (GET_MODE_SIZE (mode) > 8)
711     return true;
712 
713   return false;
714 }
715 
716 #undef  TARGET_GET_RAW_ARG_MODE
717 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
718 
719 static enum machine_mode
msp430_get_raw_arg_mode(int regno)720 msp430_get_raw_arg_mode (int regno)
721 {
722   return (regno == ARG_POINTER_REGNUM) ? VOIDmode : Pmode;
723 }
724 
725 #undef  TARGET_GET_RAW_RESULT_MODE
726 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
727 
728 static enum machine_mode
msp430_get_raw_result_mode(int regno ATTRIBUTE_UNUSED)729 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED)
730 {
731   return Pmode;
732 }
733 
734 #undef  TARGET_GIMPLIFY_VA_ARG_EXPR
735 #define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
736 
737 #include "gimplify.h"
738 #include "gimple-expr.h"
739 
740 static tree
msp430_gimplify_va_arg_expr(tree valist,tree type,gimple_seq * pre_p,gimple_seq * post_p)741 msp430_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
742 			  gimple_seq *post_p)
743 {
744   tree addr, t, type_size, rounded_size, valist_tmp;
745   unsigned HOST_WIDE_INT align, boundary;
746   bool indirect;
747 
748   indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
749   if (indirect)
750     type = build_pointer_type (type);
751 
752   align = PARM_BOUNDARY / BITS_PER_UNIT;
753   boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
754 
755   /* When we align parameter on stack for caller, if the parameter
756      alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
757      aligned at MAX_SUPPORTED_STACK_ALIGNMENT.  We will match callee
758      here with caller.  */
759   if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
760     boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
761 
762   boundary /= BITS_PER_UNIT;
763 
764   /* Hoist the valist value into a temporary for the moment.  */
765   valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
766 
767   /* va_list pointer is aligned to PARM_BOUNDARY.  If argument actually
768      requires greater alignment, we must perform dynamic alignment.  */
769   if (boundary > align
770       && !integer_zerop (TYPE_SIZE (type)))
771     {
772       /* FIXME: This is where this function diverts from targhooks.c:
773 	 std_gimplify_va_arg_expr().  It works, but I do not know why...  */
774       if (! POINTER_TYPE_P (type))
775 	{
776 	  t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
777 		      fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
778 	  gimplify_and_add (t, pre_p);
779 
780 	  t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
781 		      fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
782 				   valist_tmp,
783 				   build_int_cst (TREE_TYPE (valist), -boundary)));
784 	  gimplify_and_add (t, pre_p);
785 	}
786     }
787   else
788     boundary = align;
789 
790   /* If the actual alignment is less than the alignment of the type,
791      adjust the type accordingly so that we don't assume strict alignment
792      when dereferencing the pointer.  */
793   boundary *= BITS_PER_UNIT;
794   if (boundary < TYPE_ALIGN (type))
795     {
796       type = build_variant_type_copy (type);
797       TYPE_ALIGN (type) = boundary;
798     }
799 
800   /* Compute the rounded size of the type.  */
801   type_size = size_in_bytes (type);
802   rounded_size = round_up (type_size, align);
803 
804   /* Reduce rounded_size so it's sharable with the postqueue.  */
805   gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
806 
807   /* Get AP.  */
808   addr = valist_tmp;
809 
810   /* Compute new value for AP.  */
811   t = fold_build_pointer_plus (valist_tmp, rounded_size);
812   t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
813   gimplify_and_add (t, pre_p);
814 
815   addr = fold_convert (build_pointer_type (type), addr);
816 
817   if (indirect)
818     addr = build_va_arg_indirect_ref (addr);
819 
820   addr = build_va_arg_indirect_ref (addr);
821 
822   return addr;
823 }
824 
825 /* Addressing Modes */
826 
827 #undef  TARGET_LEGITIMATE_ADDRESS_P
828 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
829 
830 static bool
reg_ok_for_addr(rtx r,bool strict)831 reg_ok_for_addr (rtx r, bool strict)
832 {
833   int rn = REGNO (r);
834 
835   if (strict && rn >= FIRST_PSEUDO_REGISTER)
836     rn = reg_renumber [rn];
837   if (strict && 0 <= rn && rn < FIRST_PSEUDO_REGISTER)
838     return true;
839   if (!strict)
840     return true;
841   return false;
842 }
843 
844 bool
msp430_legitimate_address_p(enum machine_mode mode ATTRIBUTE_UNUSED,rtx x ATTRIBUTE_UNUSED,bool strict ATTRIBUTE_UNUSED)845 msp430_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
846 			     rtx x ATTRIBUTE_UNUSED,
847 			     bool strict ATTRIBUTE_UNUSED)
848 {
849   switch (GET_CODE (x))
850     {
851     case MEM:
852       return false;
853 
854     case PLUS:
855       if (REG_P (XEXP (x, 0)))
856 	{
857 	  if (GET_MODE (x) != GET_MODE (XEXP (x, 0)))
858 	    return false;
859 	  if (!reg_ok_for_addr (XEXP (x, 0), strict))
860 	    return false;
861 	  switch (GET_CODE (XEXP (x, 1)))
862 	    {
863 	    case CONST:
864 	    case SYMBOL_REF:
865 	    case CONST_INT:
866 	      return true;
867 	    default:
868 	      return false;
869 	    }
870 	}
871       return false;
872 
873     case REG:
874       if (!reg_ok_for_addr (x, strict))
875 	return false;
876       /* else... */
877     case CONST:
878     case SYMBOL_REF:
879     case CONST_INT:
880       return true;
881 
882     default:
883       return false;
884     }
885 }
886 
887 #undef  TARGET_LEGITIMATE_CONSTANT_P
888 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
889 
890 static bool
msp430_legitimate_constant(enum machine_mode mode,rtx x)891 msp430_legitimate_constant (enum machine_mode mode, rtx x)
892 {
893   return ! CONST_INT_P (x)
894     || mode != PSImode
895     /* GCC does not know the width of the PSImode, so make
896        sure that it does not try to use a constant value that
897        is out of range.  */
898     || (INTVAL (x) < (1 << 20) && INTVAL (x) >= (-1 << 20));
899 }
900 
901 
902 #undef  TARGET_RTX_COSTS
903 #define TARGET_RTX_COSTS msp430_rtx_costs
904 
msp430_rtx_costs(rtx x ATTRIBUTE_UNUSED,int code,int outer_code ATTRIBUTE_UNUSED,int opno ATTRIBUTE_UNUSED,int * total,bool speed ATTRIBUTE_UNUSED)905 static bool msp430_rtx_costs (rtx   x ATTRIBUTE_UNUSED,
906 			      int   code,
907 			      int   outer_code ATTRIBUTE_UNUSED,
908 			      int   opno ATTRIBUTE_UNUSED,
909 			      int * total,
910 			      bool  speed ATTRIBUTE_UNUSED)
911 {
912   switch (code)
913     {
914     case SIGN_EXTEND:
915       if (GET_MODE (x) == SImode && outer_code == SET)
916 	{
917 	  *total = COSTS_N_INSNS (4);
918 	  return true;
919 	}
920       break;
921     case ASHIFT:
922     case ASHIFTRT:
923     case LSHIFTRT:
924       if (!msp430x)
925 	{
926 	  *total = COSTS_N_INSNS (100);
927 	  return true;
928 	}
929       break;
930     }
931   return false;
932 }
933 
934 /* Function Entry and Exit */
935 
936 /* The MSP430 call frame looks like this:
937 
938    <higher addresses>
939    +--------------------+
940    |                    |
941    | Stack Arguments    |
942    |                    |
943    +--------------------+ <-- "arg pointer"
944    |                    |
945    | PC from call       |  (2 bytes for 430, 4 for TARGET_LARGE)
946    |                    |
947    +--------------------+
948    | SR if this func has|
949    | been called via an |
950    | interrupt.         |
951    +--------------------+  <-- SP before prologue, also AP
952    |                    |
953    | Saved Regs         |  (2 bytes per reg for 430, 4 per for TARGET_LARGE)
954    |                    |
955    +--------------------+  <-- "frame pointer"
956    |                    |
957    | Locals             |
958    |                    |
959    +--------------------+
960    |                    |
961    | Outgoing Args      |
962    |                    |
963    +--------------------+  <-- SP during function
964    <lower addresses>
965 
966 */
967 
968 /* We use this to wrap all emitted insns in the prologue, so they get
969    the "frame-related" (/f) flag set.  */
970 static rtx
F(rtx x)971 F (rtx x)
972 {
973   RTX_FRAME_RELATED_P (x) = 1;
974   return x;
975 }
976 
977 /* This is the one spot that decides if a register is to be saved and
978    restored in the prologue/epilogue.  */
979 static bool
msp430_preserve_reg_p(int regno)980 msp430_preserve_reg_p (int regno)
981 {
982   /* PC, SP, SR, and the constant generator.  */
983   if (regno <= 3)
984     return false;
985 
986   /* FIXME: add interrupt, EH, etc.  */
987   if (crtl->calls_eh_return)
988     return true;
989 
990   /* Shouldn't be more than the above, but just in case...  */
991   if (fixed_regs [regno])
992     return false;
993 
994   /* Interrupt handlers save all registers they use, even
995      ones which are call saved.  If they call other functions
996      then *every* register is saved.  */
997   if (msp430_is_interrupt_func ())
998     return ! crtl->is_leaf || df_regs_ever_live_p (regno);
999 
1000   if (!call_used_regs [regno]
1001       && df_regs_ever_live_p (regno))
1002     return true;
1003 
1004   return false;
1005 }
1006 
1007 /* Compute all the frame-related fields in our machine_function
1008    structure.  */
1009 static void
msp430_compute_frame_info(void)1010 msp430_compute_frame_info (void)
1011 {
1012   int i;
1013 
1014   cfun->machine->computed = 1;
1015   cfun->machine->framesize_regs = 0;
1016   cfun->machine->framesize_locals = get_frame_size ();
1017   cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
1018 
1019   for (i = 0; i < ARG_POINTER_REGNUM; i ++)
1020     if (msp430_preserve_reg_p (i))
1021       {
1022 	cfun->machine->need_to_save [i] = 1;
1023 	cfun->machine->framesize_regs += (TARGET_LARGE ? 4 : 2);
1024       }
1025     else
1026       cfun->machine->need_to_save [i] = 0;
1027 
1028   if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
1029     cfun->machine->framesize_locals ++;
1030 
1031   cfun->machine->framesize = (cfun->machine->framesize_regs
1032 			      + cfun->machine->framesize_locals
1033 			      + cfun->machine->framesize_outgoing);
1034 }
1035 
1036 static inline bool
is_attr_func(const char * attr)1037 is_attr_func (const char * attr)
1038 {
1039   return lookup_attribute (attr, DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE;
1040 }
1041 
1042 /* Returns true if the current function has the "interrupt" attribute.  */
1043 
1044 bool
msp430_is_interrupt_func(void)1045 msp430_is_interrupt_func (void)
1046 {
1047   if (current_function_decl == NULL)
1048     return false;
1049   return is_attr_func ("interrupt");
1050 }
1051 
1052 static bool
is_wakeup_func(void)1053 is_wakeup_func (void)
1054 {
1055   return msp430_is_interrupt_func () && is_attr_func ("wakeup");
1056 }
1057 
1058 static inline bool
is_naked_func(void)1059 is_naked_func (void)
1060 {
1061   return is_attr_func ("naked");
1062 }
1063 
1064 static inline bool
is_reentrant_func(void)1065 is_reentrant_func (void)
1066 {
1067   return is_attr_func ("reentrant");
1068 }
1069 
1070 static inline bool
is_critical_func(void)1071 is_critical_func (void)
1072 {
1073   return is_attr_func ("critical");
1074 }
1075 
1076 #undef  TARGET_ASM_FUNCTION_PROLOGUE
1077 #define TARGET_ASM_FUNCTION_PROLOGUE	msp430_start_function
1078 
1079 static void
msp430_start_function(FILE * outfile,HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)1080 msp430_start_function (FILE *outfile, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
1081 {
1082   int r, n;
1083 
1084   fprintf (outfile, "; start of function\n");
1085 
1086   if (DECL_ATTRIBUTES (current_function_decl) != NULL_TREE)
1087     {
1088       fprintf (outfile, "; attributes: ");
1089       if (is_naked_func ())
1090 	fprintf (outfile, "naked ");
1091       if (msp430_is_interrupt_func ())
1092 	fprintf (outfile, "interrupt ");
1093       if (is_reentrant_func ())
1094 	fprintf (outfile, "reentrant ");
1095       if (is_critical_func ())
1096 	fprintf (outfile, "critical ");
1097       if (is_wakeup_func ())
1098 	fprintf (outfile, "wakeup ");
1099       fprintf (outfile, "\n");
1100     }
1101 
1102   fprintf (outfile, "; framesize_regs:     %d\n", cfun->machine->framesize_regs);
1103   fprintf (outfile, "; framesize_locals:   %d\n", cfun->machine->framesize_locals);
1104   fprintf (outfile, "; framesize_outgoing: %d\n", cfun->machine->framesize_outgoing);
1105   fprintf (outfile, "; framesize:          %d\n", cfun->machine->framesize);
1106   fprintf (outfile, "; elim ap -> fp       %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM));
1107   fprintf (outfile, "; elim fp -> sp       %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM));
1108 
1109   n = 0;
1110   fprintf (outfile, "; saved regs:");
1111   for (r = 0; r < ARG_POINTER_REGNUM; r++)
1112     if (cfun->machine->need_to_save [r])
1113       {
1114 	fprintf (outfile, " %s", reg_names [r]);
1115 	n = 1;
1116       }
1117   if (n == 0)
1118     fprintf (outfile, "(none)");
1119   fprintf (outfile, "\n");
1120 }
1121 
1122 /* Common code to change the stack pointer.  */
1123 static void
increment_stack(HOST_WIDE_INT amount)1124 increment_stack (HOST_WIDE_INT amount)
1125 {
1126   rtx inc;
1127   rtx sp =  stack_pointer_rtx;
1128 
1129   if (amount == 0)
1130     return;
1131 
1132   if (amount < 0)
1133     {
1134       inc = GEN_INT (- amount);
1135       if (TARGET_LARGE)
1136 	F (emit_insn (gen_subpsi3 (sp, sp, inc)));
1137       else
1138 	F (emit_insn (gen_subhi3 (sp, sp, inc)));
1139     }
1140   else
1141     {
1142       inc = GEN_INT (amount);
1143       if (TARGET_LARGE)
1144 	emit_insn (gen_addpsi3 (sp, sp, inc));
1145       else
1146 	emit_insn (gen_addhi3 (sp, sp, inc));
1147     }
1148 }
1149 
1150 /* Verify MSP430 specific attributes.  */
1151 
1152 static tree
msp430_attr(tree * node,tree name,tree args,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)1153 msp430_attr (tree * node,
1154 	     tree   name,
1155 	     tree   args,
1156 	     int    flags ATTRIBUTE_UNUSED,
1157 	     bool * no_add_attrs)
1158 {
1159   gcc_assert (DECL_P (* node));
1160 
1161   if (args != NULL)
1162     {
1163       tree value = TREE_VALUE (args);
1164 
1165       switch (TREE_CODE (value))
1166 	{
1167 	case STRING_CST:
1168 	  if (   strcmp (TREE_STRING_POINTER (value), "reset")
1169 	      && strcmp (TREE_STRING_POINTER (value), "nmi")
1170 	      && strcmp (TREE_STRING_POINTER (value), "watchdog"))
1171 	    /* Allow the attribute to be added - the linker script
1172 	       being used may still recognise this name.  */
1173 	    warning (OPT_Wattributes,
1174 		     "unrecognised interrupt vector argument of %qE attribute",
1175 		     name);
1176 	  break;
1177 
1178 	case INTEGER_CST:
1179 	  if (TREE_INT_CST_LOW (value) > 63)
1180 	    /* Allow the attribute to be added - the linker script
1181 	       being used may still recognise this value.  */
1182 	    warning (OPT_Wattributes,
1183 		     "numeric argument of %qE attribute must be in range 0..63",
1184 		     name);
1185 	  break;
1186 
1187 	default:
1188 	  warning (OPT_Wattributes,
1189 		   "argument of %qE attribute is not a string constant or number",
1190 		   name);
1191 	  *no_add_attrs = true;
1192 	  break;
1193 	}
1194     }
1195 
1196   if (TREE_CODE (* node) != FUNCTION_DECL)
1197     {
1198       warning (OPT_Wattributes,
1199 	       "%qE attribute only applies to functions",
1200 	       name);
1201       * no_add_attrs = true;
1202     }
1203 
1204   /* FIXME: We ought to check that the interrupt handler
1205      attribute has been applied to a void function.  */
1206   /* FIXME: We should check that reentrant and critical
1207      functions are not naked and that critical functions
1208      are not reentrant.  */
1209 
1210   return NULL_TREE;
1211 }
1212 
1213 #undef  TARGET_ATTRIBUTE_TABLE
1214 #define TARGET_ATTRIBUTE_TABLE		msp430_attribute_table
1215 
1216 /* Table of MSP430-specific attributes.  */
1217 const struct attribute_spec msp430_attribute_table[] =
1218 {
1219   /* Name          min_len  decl_req,    fn_type_req,    affects_type_identity
1220                        max_len,  type_req,        handler.  */
1221   { "interrupt",      0, 1, true,  false, false, msp430_attr, false },
1222   { "naked",          0, 0, true,  false, false, msp430_attr, false },
1223   { "reentrant",      0, 0, true,  false, false, msp430_attr, false },
1224   { "critical",       0, 0, true,  false, false, msp430_attr, false },
1225   { "wakeup",         0, 0, true,  false, false, msp430_attr, false },
1226   { NULL,             0, 0, false, false, false, NULL,        false }
1227 };
1228 
1229 void
msp430_start_function(FILE * file,const char * name,tree decl)1230 msp430_start_function (FILE *file, const char *name, tree decl)
1231 {
1232   tree int_attr;
1233 
1234   int_attr = lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl));
1235   if (int_attr != NULL_TREE)
1236     {
1237       tree intr_vector = TREE_VALUE (int_attr);
1238 
1239       if (intr_vector != NULL_TREE)
1240 	{
1241 	  char buf[101];
1242 
1243 	  intr_vector = TREE_VALUE (intr_vector);
1244 
1245 	  /* The interrupt attribute has a vector value.  Turn this into a
1246 	     section name, switch to that section and put the address of
1247 	     the current function into that vector slot.  Note msp430_attr()
1248 	     has already verified the vector name for us.  */
1249 	  if (TREE_CODE (intr_vector) == STRING_CST)
1250 	    sprintf (buf, "__interrupt_vector_%.80s",
1251 		     TREE_STRING_POINTER (intr_vector));
1252 	  else /* TREE_CODE (intr_vector) == INTEGER_CST */
1253 	    sprintf (buf, "__interrupt_vector_%u",
1254 		     (unsigned int) TREE_INT_CST_LOW (intr_vector));
1255 
1256 	  switch_to_section (get_section (buf, SECTION_CODE, decl));
1257 	  fputs ("\t.word\t", file);
1258 	  assemble_name (file, name);
1259 	  fputc ('\n', file);
1260 	  fputc ('\t', file);
1261 	}
1262     }
1263 
1264   switch_to_section (function_section (decl));
1265   ASM_OUTPUT_FUNCTION_LABEL (file, name, decl);
1266 }
1267 
1268 static section *
msp430_function_section(tree decl,enum node_frequency freq,bool startup,bool exit)1269 msp430_function_section (tree decl, enum node_frequency freq, bool startup, bool exit)
1270 {
1271   /* In large mode we must make sure that interrupt handlers are put into
1272      low memory as the vector table only accepts 16-bit addresses.  */
1273   if (TARGET_LARGE
1274       && lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl)))
1275     return get_section (".lowtext", SECTION_CODE | SECTION_WRITE , decl);
1276 
1277   /* Otherwise, use the default function section.  */
1278   return default_function_section (decl, freq, startup, exit);
1279 }
1280 
1281 #undef  TARGET_ASM_FUNCTION_SECTION
1282 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
1283 
1284 enum msp430_builtin
1285 {
1286   MSP430_BUILTIN_BIC_SR,
1287   MSP430_BUILTIN_BIS_SR,
1288   MSP430_BUILTIN_max
1289 };
1290 
1291 static GTY(()) tree msp430_builtins [(int) MSP430_BUILTIN_max];
1292 
1293 static void
msp430_init_builtins(void)1294 msp430_init_builtins (void)
1295 {
1296   tree void_ftype_int = build_function_type_list (void_type_node, integer_type_node, NULL);
1297 
1298   msp430_builtins[MSP430_BUILTIN_BIC_SR] =
1299     add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int,
1300 			   MSP430_BUILTIN_BIC_SR, BUILT_IN_MD, NULL, NULL_TREE);
1301 
1302   msp430_builtins[MSP430_BUILTIN_BIS_SR] =
1303     add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int,
1304 			   MSP430_BUILTIN_BIS_SR, BUILT_IN_MD, NULL, NULL_TREE);
1305 }
1306 
1307 static tree
msp430_builtin_decl(unsigned code,bool initialize ATTRIBUTE_UNUSED)1308 msp430_builtin_decl (unsigned code, bool initialize ATTRIBUTE_UNUSED)
1309 {
1310   switch (code)
1311     {
1312     case MSP430_BUILTIN_BIC_SR:
1313     case MSP430_BUILTIN_BIS_SR:
1314       return msp430_builtins[code];
1315     default:
1316       return error_mark_node;
1317     }
1318 }
1319 
1320 static rtx
msp430_expand_builtin(tree exp,rtx target ATTRIBUTE_UNUSED,rtx subtarget ATTRIBUTE_UNUSED,enum machine_mode mode ATTRIBUTE_UNUSED,int ignore ATTRIBUTE_UNUSED)1321 msp430_expand_builtin (tree exp,
1322 		       rtx target ATTRIBUTE_UNUSED,
1323 		       rtx subtarget ATTRIBUTE_UNUSED,
1324 		       enum machine_mode mode ATTRIBUTE_UNUSED,
1325 		       int ignore ATTRIBUTE_UNUSED)
1326 {
1327   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
1328   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
1329   rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
1330 
1331   if (! msp430_is_interrupt_func ())
1332     {
1333       error ("MSP430 builtin functions only work inside interrupt handlers");
1334       return NULL_RTX;
1335     }
1336 
1337   if (! REG_P (arg1) && ! CONSTANT_P (arg1))
1338     arg1 = force_reg (mode, arg1);
1339 
1340   switch (fcode)
1341     {
1342     case MSP430_BUILTIN_BIC_SR:  emit_insn (gen_bic_SR (arg1)); break;
1343     case MSP430_BUILTIN_BIS_SR:  emit_insn (gen_bis_SR (arg1)); break;
1344     default:
1345       internal_error ("bad builtin code");
1346       break;
1347     }
1348   return NULL_RTX;
1349 }
1350 
1351 #undef  TARGET_INIT_BUILTINS
1352 #define TARGET_INIT_BUILTINS  msp430_init_builtins
1353 
1354 #undef  TARGET_EXPAND_BUILTIN
1355 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
1356 
1357 #undef  TARGET_BUILTIN_DECL
1358 #define TARGET_BUILTIN_DECL   msp430_builtin_decl
1359 
1360 void
msp430_expand_prologue(void)1361 msp430_expand_prologue (void)
1362 {
1363   int i, j;
1364   int fs;
1365   /* Always use stack_pointer_rtx instead of calling
1366      rtx_gen_REG ourselves.  Code elsewhere in GCC assumes
1367      that there is a single rtx representing the stack pointer,
1368      namely stack_pointer_rtx, and uses == to recognize it.  */
1369   rtx sp = stack_pointer_rtx;
1370   rtx p;
1371 
1372   if (is_naked_func ())
1373     return;
1374 
1375   emit_insn (gen_prologue_start_marker ());
1376 
1377   if (is_critical_func ())
1378     {
1379       emit_insn (gen_push_intr_state ());
1380       emit_insn (gen_disable_interrupts ());
1381     }
1382   else if (is_reentrant_func ())
1383     emit_insn (gen_disable_interrupts ());
1384 
1385   if (!cfun->machine->computed)
1386     msp430_compute_frame_info ();
1387 
1388   if (flag_stack_usage_info)
1389     current_function_static_stack_size = cfun->machine->framesize;
1390 
1391   if (crtl->args.pretend_args_size)
1392     {
1393       rtx note;
1394 
1395       gcc_assert (crtl->args.pretend_args_size == 2);
1396 
1397       p = emit_insn (gen_grow_and_swap ());
1398 
1399       /* Document the stack decrement...  */
1400       note = F (gen_rtx_SET (Pmode, stack_pointer_rtx,
1401 			     gen_rtx_MINUS (Pmode, stack_pointer_rtx, GEN_INT (2))));
1402       add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
1403 
1404       /* ...and the establishment of a new location for the return address.  */
1405       note = F (gen_rtx_SET (Pmode, gen_rtx_MEM (Pmode,
1406 						 gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-2))),
1407 			     pc_rtx));
1408       add_reg_note (p, REG_CFA_OFFSET, note);
1409       F (p);
1410     }
1411 
1412   for (i = 15; i >= 4; i--)
1413     if (cfun->machine->need_to_save [i])
1414       {
1415 	int seq, count;
1416 	rtx note;
1417 
1418 	for (seq = i - 1; seq >= 4 && cfun->machine->need_to_save[seq]; seq --)
1419 	  ;
1420 	count = i - seq;
1421 
1422 	if (msp430x)
1423 	  {
1424 	    /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger.  */
1425 	    p = F (emit_insn (gen_pushm (gen_rtx_REG (Pmode, i),
1426 					 GEN_INT (count))));
1427 
1428 	    note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1));
1429 
1430 	    XVECEXP (note, 0, 0)
1431 	      = F (gen_rtx_SET (VOIDmode,
1432 			     stack_pointer_rtx,
1433 			     gen_rtx_PLUS (Pmode,
1434 					   stack_pointer_rtx,
1435 					   GEN_INT (count * (TARGET_LARGE ? -4 : -2)))));
1436 
1437 	    /* *sp-- = R[i-j] */
1438 	    /* sp+N	R10
1439 	       ...
1440 	       sp	R4  */
1441 	    for (j = 0; j < count; j ++)
1442 	      {
1443 		rtx addr;
1444 		int ofs = (count - j - 1) * (TARGET_LARGE ? 4 : 2);
1445 
1446 		if (ofs)
1447 		  addr = gen_rtx_PLUS (Pmode, sp, GEN_INT (ofs));
1448 		else
1449 		  addr = stack_pointer_rtx;
1450 
1451 		XVECEXP (note, 0, j + 1) =
1452 		  F (gen_rtx_SET (VOIDmode,
1453 				  gen_rtx_MEM (Pmode, addr),
1454 				  gen_rtx_REG (Pmode, i - j)) );
1455 	      }
1456 
1457 	    add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
1458 	    i -= count - 1;
1459 	  }
1460 	else
1461 	  F (emit_insn (gen_push (gen_rtx_REG (Pmode, i))));
1462       }
1463 
1464   if (frame_pointer_needed)
1465     F (emit_move_insn (gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM), sp));
1466 
1467   fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1468 
1469   increment_stack (- fs);
1470 
1471   emit_insn (gen_prologue_end_marker ());
1472 }
1473 
1474 void
msp430_expand_epilogue(int is_eh)1475 msp430_expand_epilogue (int is_eh)
1476 {
1477   int i;
1478   int fs;
1479   int helper_n = 0;
1480 
1481   if (is_naked_func ())
1482     return;
1483 
1484   if (cfun->machine->need_to_save [10])
1485     {
1486       /* Check for a helper function.  */
1487       helper_n = 7; /* For when the loop below never sees a match.  */
1488       for (i = 9; i >= 4; i--)
1489 	if (!cfun->machine->need_to_save [i])
1490 	  {
1491 	    helper_n = 10 - i;
1492 	    for (; i >= 4; i--)
1493 	      if (cfun->machine->need_to_save [i])
1494 		{
1495 		  helper_n = 0;
1496 		  break;
1497 		}
1498 	    break;
1499 	  }
1500     }
1501 
1502   emit_insn (gen_epilogue_start_marker ());
1503 
1504   if (cfun->decl && strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun->decl)), "main") == 0)
1505     emit_insn (gen_msp430_refsym_need_exit ());
1506 
1507   if (is_wakeup_func ())
1508     /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
1509        status register current residing on the stack.  When this function
1510        executes its RETI instruction the SR will be updated with this saved
1511        value, thus ensuring that the processor is woken up from any low power
1512        state in which it may be residing.  */
1513     emit_insn (gen_bic_SR (GEN_INT (0xf0)));
1514 
1515   fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1516 
1517   increment_stack (fs);
1518 
1519   if (is_eh)
1520     {
1521       /* We need to add the right "SP" register save just after the
1522 	 regular ones, so that when we pop it off we're in the EH
1523 	 return frame, not this one.  This overwrites our own return
1524 	 address, but we're not going to be returning anyway.  */
1525       rtx r12 = gen_rtx_REG (Pmode, 12);
1526       rtx (*addPmode)(rtx, rtx, rtx) = TARGET_LARGE ? gen_addpsi3 : gen_addhi3;
1527 
1528       /* R12 will hold the new SP.  */
1529       i = cfun->machine->framesize_regs;
1530       emit_move_insn (r12, stack_pointer_rtx);
1531       emit_insn (addPmode (r12, r12, EH_RETURN_STACKADJ_RTX));
1532       emit_insn (addPmode (r12, r12, GEN_INT (i)));
1533       emit_move_insn (gen_rtx_MEM (Pmode, plus_constant (Pmode, stack_pointer_rtx, i)), r12);
1534     }
1535 
1536   for (i = 4; i <= 15; i++)
1537     if (cfun->machine->need_to_save [i])
1538       {
1539 	int seq, count;
1540 
1541 	for (seq = i + 1; seq <= 15 && cfun->machine->need_to_save[seq]; seq ++)
1542 	  ;
1543 	count = seq - i;
1544 
1545 	if (msp430x)
1546 	  {
1547 	    /* Note: With TARGET_LARGE we still use
1548 	       POPM as POPX.A is two bytes bigger.  */
1549 	    emit_insn (gen_popm (stack_pointer_rtx, GEN_INT (seq - 1),
1550 				 GEN_INT (count)));
1551 	    i += count - 1;
1552 	  }
1553 	else if (i == 11 - helper_n
1554 		 && ! msp430_is_interrupt_func ()
1555 		 && ! is_reentrant_func ()
1556 		 && ! is_critical_func ()
1557 		 && crtl->args.pretend_args_size == 0
1558 		 /* Calling the helper takes as many bytes as the POP;RET sequence.  */
1559 		 && helper_n > 1
1560 		 && !is_eh)
1561 	  {
1562 	    emit_insn (gen_epilogue_helper (GEN_INT (helper_n)));
1563 	    return;
1564 	  }
1565 	else
1566 	  emit_insn (gen_pop (gen_rtx_REG (Pmode, i)));
1567       }
1568 
1569   if (is_eh)
1570     {
1571       /* Also pop SP, which puts us into the EH return frame.  Except
1572 	 that you can't "pop" sp, you have to just load it off the
1573 	 stack.  */
1574       emit_move_insn (stack_pointer_rtx, gen_rtx_MEM (Pmode, stack_pointer_rtx));
1575     }
1576 
1577   if (crtl->args.pretend_args_size)
1578     emit_insn (gen_swap_and_shrink ());
1579 
1580   if (is_critical_func ())
1581     emit_insn (gen_pop_intr_state ());
1582   else if (is_reentrant_func ())
1583     emit_insn (gen_enable_interrupts ());
1584 
1585   emit_jump_insn (gen_msp_return ());
1586 }
1587 
1588 /* Implements EH_RETURN_STACKADJ_RTX.  Saved and used later in
1589    m32c_emit_eh_epilogue.  */
1590 rtx
msp430_eh_return_stackadj_rtx(void)1591 msp430_eh_return_stackadj_rtx (void)
1592 {
1593   if (!cfun->machine->eh_stack_adjust)
1594     {
1595       rtx sa;
1596 
1597       sa = gen_rtx_REG (Pmode, 15);
1598       cfun->machine->eh_stack_adjust = sa;
1599     }
1600   return cfun->machine->eh_stack_adjust;
1601 }
1602 
1603 /* This function is called before reload, to "fix" the stack in
1604    preparation for an EH return.  */
1605 void
msp430_expand_eh_return(rtx eh_handler)1606 msp430_expand_eh_return (rtx eh_handler)
1607 {
1608   /* These are all Pmode */
1609   rtx ap, sa, ra, tmp;
1610 
1611   ap = arg_pointer_rtx;
1612   sa = msp430_eh_return_stackadj_rtx ();
1613   ra = eh_handler;
1614 
1615   tmp = ap;
1616   tmp = gen_rtx_PLUS (Pmode, ap, sa);
1617   tmp = plus_constant (Pmode, tmp, TARGET_LARGE ? -4 : -2);
1618   tmp = gen_rtx_MEM (Pmode, tmp);
1619   emit_move_insn (tmp, ra);
1620 }
1621 
1622 /* This is a list of MD patterns that implement fixed-count shifts.  */
1623 static struct
1624 {
1625   const char *name;
1626   int count;
1627   int need_430x;
1628   rtx (*genfunc)(rtx,rtx);
1629 }
1630   const_shift_helpers[] =
1631 {
1632 #define CSH(N,C,X,G) { "__mspabi_"N, C, X, gen_##G }
1633 
1634   CSH ("slli", 1, 1, slli_1),
1635   CSH ("slll", 1, 1, slll_1),
1636   CSH ("slll", 2, 1, slll_2),
1637 
1638   CSH ("srai", 1, 0, srai_1),
1639   CSH ("sral", 1, 0, sral_1),
1640   CSH ("sral", 2, 0, sral_2),
1641 
1642   CSH ("srll", 1, 0, srll_1),
1643   CSH ("srll", 2, 1, srll_2x),
1644   { 0, 0, 0, 0 }
1645 #undef CSH
1646 };
1647 
1648 /* The MSP430 ABI defines a number of helper functions that should be
1649    used for, for example, 32-bit shifts.  This function is called to
1650    emit such a function, using the table above to optimize some
1651    cases.  */
1652 void
msp430_expand_helper(rtx * operands,const char * helper_name,bool const_variants)1653 msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variants)
1654 {
1655   rtx c, f;
1656   char *helper_const = NULL;
1657   int arg2 = 13;
1658   int arg1sz = 1;
1659   enum machine_mode arg0mode = GET_MODE (operands[0]);
1660   enum machine_mode arg1mode = GET_MODE (operands[1]);
1661   enum machine_mode arg2mode = GET_MODE (operands[2]);
1662   int have_430x = msp430x ? 1 : 0;
1663 
1664   if (CONST_INT_P (operands[2]))
1665     {
1666       int i;
1667 
1668       for (i=0; const_shift_helpers[i].name; i++)
1669 	{
1670 	  if (const_shift_helpers[i].need_430x <= have_430x
1671 	      && strcmp (helper_name, const_shift_helpers[i].name) == 0
1672 	      && INTVAL (operands[2]) == const_shift_helpers[i].count)
1673 	    {
1674 	      emit_insn (const_shift_helpers[i].genfunc (operands[0], operands[1]));
1675 	      return;
1676 	    }
1677 	}
1678     }
1679 
1680   if (arg1mode == VOIDmode)
1681     arg1mode = arg0mode;
1682   if (arg2mode == VOIDmode)
1683     arg2mode = arg0mode;
1684 
1685   if (arg1mode == SImode)
1686     {
1687       arg2 = 14;
1688       arg1sz = 2;
1689     }
1690 
1691   if (const_variants
1692       && CONST_INT_P (operands[2])
1693       && INTVAL (operands[2]) >= 1
1694       && INTVAL (operands[2]) <= 15)
1695     {
1696       /* Note that the INTVAL is limited in value and length by the conditional above.  */
1697       int len = strlen (helper_name) + 4;
1698       helper_const = (char *) xmalloc (len);
1699       snprintf (helper_const, len, "%s_%d", helper_name, (int) INTVAL (operands[2]));
1700     }
1701 
1702   emit_move_insn (gen_rtx_REG (arg1mode, 12),
1703 		  operands[1]);
1704   if (!helper_const)
1705     emit_move_insn (gen_rtx_REG (arg2mode, arg2),
1706 		    operands[2]);
1707 
1708   c = gen_call_value_internal (gen_rtx_REG (arg0mode, 12),
1709 			       gen_rtx_SYMBOL_REF (VOIDmode, helper_const ? helper_const : helper_name),
1710 			       GEN_INT (0));
1711   c = emit_call_insn (c);
1712   RTL_CONST_CALL_P (c) = 1;
1713 
1714   f = 0;
1715   use_regs (&f, 12, arg1sz);
1716   if (!helper_const)
1717     use_regs (&f, arg2, 1);
1718   add_function_usage_to (c, f);
1719 
1720   emit_move_insn (operands[0],
1721 		  gen_rtx_REG (arg0mode, 12));
1722 }
1723 
1724 /* Called by cbranch<mode>4 to coerce operands into usable forms.  */
1725 void
msp430_fixup_compare_operands(enum machine_mode my_mode,rtx * operands)1726 msp430_fixup_compare_operands (enum machine_mode my_mode, rtx * operands)
1727 {
1728   /* constants we're looking for, not constants which are allowed.  */
1729   int const_op_idx = 1;
1730 
1731   if (msp430_reversible_cmp_operator (operands[0], VOIDmode))
1732     const_op_idx = 2;
1733 
1734   if (GET_CODE (operands[const_op_idx]) != REG
1735       && GET_CODE (operands[const_op_idx]) != MEM)
1736     operands[const_op_idx] = copy_to_mode_reg (my_mode, operands[const_op_idx]);
1737 }
1738 
1739 /* Simplify_gen_subreg() doesn't handle memory references the way we
1740    need it to below, so we use this function for when we must get a
1741    valid subreg in a "natural" state.  */
1742 rtx
msp430_subreg(enum machine_mode mode,rtx r,enum machine_mode omode,int byte)1743 msp430_subreg (enum machine_mode mode, rtx r, enum machine_mode omode, int byte)
1744 {
1745   rtx rv;
1746 
1747   if (GET_CODE (r) == SUBREG
1748       && SUBREG_BYTE (r) == 0)
1749     {
1750       rtx ireg = SUBREG_REG (r);
1751       enum machine_mode imode = GET_MODE (ireg);
1752 
1753       /* special case for (HI (SI (PSI ...), 0)) */
1754       if (imode == PSImode
1755 	  && mode == HImode
1756 	  && byte == 0)
1757 	rv = gen_rtx_SUBREG (mode, ireg, byte);
1758       else
1759 	rv = simplify_gen_subreg (mode, ireg, imode, byte);
1760     }
1761   else if (GET_CODE (r) == MEM)
1762     rv = adjust_address (r, mode, byte);
1763   else
1764     rv = simplify_gen_subreg (mode, r, omode, byte);
1765 
1766   if (!rv)
1767     gcc_unreachable ();
1768 
1769   return rv;
1770 }
1771 
1772 /* Called by movsi_x to generate the HImode operands.  */
1773 void
msp430_split_movsi(rtx * operands)1774 msp430_split_movsi (rtx *operands)
1775 {
1776   rtx op00, op02, op10, op12;
1777 
1778   op00 = msp430_subreg (HImode, operands[0], SImode, 0);
1779   op02 = msp430_subreg (HImode, operands[0], SImode, 2);
1780 
1781   if (GET_CODE (operands[1]) == CONST
1782       || GET_CODE (operands[1]) == SYMBOL_REF)
1783     {
1784       op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
1785       op10 = gen_rtx_CONST (HImode, op10);
1786       op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
1787       op12 = gen_rtx_CONST (HImode, op12);
1788     }
1789   else
1790     {
1791       op10 = msp430_subreg (HImode, operands[1], SImode, 0);
1792       op12 = msp430_subreg (HImode, operands[1], SImode, 2);
1793     }
1794 
1795   if (rtx_equal_p (operands[0], operands[1]))
1796     {
1797       operands[2] = op02;
1798       operands[4] = op12;
1799       operands[3] = op00;
1800       operands[5] = op10;
1801     }
1802   else if (rtx_equal_p (op00, op12)
1803 	   /* Catch the case where we are loading (rN, rN+1) from mem (rN).  */
1804 	   || (REG_P (op00) && reg_mentioned_p (op00, op10))
1805 	   /* Or storing (rN) into mem (rN).  */
1806 	   || (REG_P (op10) && reg_mentioned_p (op10, op00))
1807 	   )
1808     {
1809       operands[2] = op02;
1810       operands[4] = op12;
1811       operands[3] = op00;
1812       operands[5] = op10;
1813     }
1814   else
1815     {
1816       operands[2] = op00;
1817       operands[4] = op10;
1818       operands[3] = op02;
1819       operands[5] = op12;
1820     }
1821 }
1822 
1823 
1824 /* The MSPABI specifies the names of various helper functions, many of
1825    which are compatible with GCC's helpers.  This table maps the GCC
1826    name to the MSPABI name.  */
1827 static const struct
1828 {
1829   char const * const gcc_name;
1830   char const * const ti_name;
1831 }
1832   helper_function_name_mappings [] =
1833 {
1834   /* Floating point to/from integer conversions.  */
1835   { "__truncdfsf2", "__mspabi_cvtdf" },
1836   { "__extendsfdf2", "__mspabi_cvtfd" },
1837   { "__fixdfhi", "__mspabi_fixdi" },
1838   { "__fixdfsi", "__mspabi_fixdli" },
1839   { "__fixdfdi", "__mspabi_fixdlli" },
1840   { "__fixunsdfhi", "__mspabi_fixdu" },
1841   { "__fixunsdfsi", "__mspabi_fixdul" },
1842   { "__fixunsdfdi", "__mspabi_fixdull" },
1843   { "__fixsfhi", "__mspabi_fixfi" },
1844   { "__fixsfsi", "__mspabi_fixfli" },
1845   { "__fixsfdi", "__mspabi_fixflli" },
1846   { "__fixunsfhi", "__mspabi_fixfu" },
1847   { "__fixunsfsi", "__mspabi_fixful" },
1848   { "__fixunsfdi", "__mspabi_fixfull" },
1849   { "__floathisf", "__mspabi_fltif" },
1850   { "__floatsisf", "__mspabi_fltlif" },
1851   { "__floatdisf", "__mspabi_fltllif" },
1852   { "__floathidf", "__mspabi_fltid" },
1853   { "__floatsidf", "__mspabi_fltlid" },
1854   { "__floatdidf", "__mspabi_fltllid" },
1855   { "__floatunhisf", "__mspabi_fltuf" },
1856   { "__floatunsisf", "__mspabi_fltulf" },
1857   { "__floatundisf", "__mspabi_fltullf" },
1858   { "__floatunhidf", "__mspabi_fltud" },
1859   { "__floatunsidf", "__mspabi_fltuld" },
1860   { "__floatundidf", "__mspabi_fltulld" },
1861 
1862   /* Floating point comparisons.  */
1863   /* GCC uses individual functions for each comparison, TI uses one
1864      compare <=> function.  */
1865 
1866   /* Floating point arithmatic */
1867   { "__adddf3", "__mspabi_addd" },
1868   { "__addsf3", "__mspabi_addf" },
1869   { "__divdf3", "__mspabi_divd" },
1870   { "__divsf3", "__mspabi_divf" },
1871   { "__muldf3", "__mspabi_mpyd" },
1872   { "__mulsf3", "__mspabi_mpyf" },
1873   { "__subdf3", "__mspabi_subd" },
1874   { "__subsf3", "__mspabi_subf" },
1875   /* GCC does not use helper functions for negation */
1876 
1877   /* Integer multiply, divide, remainder.  */
1878   { "__mulhi3", "__mspabi_mpyi" },
1879   { "__mulsi3", "__mspabi_mpyl" },
1880   { "__muldi3", "__mspabi_mpyll" },
1881 #if 0
1882   /* Clarify signed vs unsigned first.  */
1883   { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
1884   { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
1885 #endif
1886 
1887   { "__divhi3", "__mspabi_divi" },
1888   { "__divsi3", "__mspabi_divli" },
1889   { "__divdi3", "__mspabi_divlli" },
1890   { "__udivhi3", "__mspabi_divu" },
1891   { "__udivsi3", "__mspabi_divlu" },
1892   { "__udivdi3", "__mspabi_divllu" },
1893   { "__modhi3", "__mspabi_remi" },
1894   { "__modsi3", "__mspabi_remli" },
1895   { "__moddi3", "__mspabi_remlli" },
1896   { "__umodhi3", "__mspabi_remu" },
1897   { "__umodsi3", "__mspabi_remul" },
1898   { "__umoddi3", "__mspabi_remull" },
1899 
1900   /* Bitwise operations.  */
1901   /* Rotation - no rotation support yet.  */
1902   /* Logical left shift - gcc already does these itself.  */
1903   /* Arithmetic left shift - gcc already does these itself.  */
1904   /* Arithmetic right shift - gcc already does these itself.  */
1905 
1906   { NULL, NULL }
1907 };
1908 
1909 /* Returns true if the current MCU is an F5xxx series.  */
1910 bool
msp430_use_f5_series_hwmult(void)1911 msp430_use_f5_series_hwmult (void)
1912 {
1913   if (msp430_hwmult_type == F5SERIES)
1914     return true;
1915 
1916   if (target_mcu == NULL || msp430_hwmult_type != AUTO)
1917     return false;
1918 
1919   return strncasecmp (target_mcu, "msp430f5", 8) == 0;
1920 }
1921 
1922 /* Returns true id the current MCU has a second generation 32-bit hardware multiplier.  */
1923 static bool
use_32bit_hwmult(void)1924 use_32bit_hwmult (void)
1925 {
1926   static const char * known_32bit_mult_mcus [] =
1927     {
1928       "msp430f4783",      "msp430f4793",      "msp430f4784",
1929       "msp430f4794",      "msp430f47126",     "msp430f47127",
1930       "msp430f47163",     "msp430f47173",     "msp430f47183",
1931       "msp430f47193",     "msp430f47166",     "msp430f47176",
1932       "msp430f47186",     "msp430f47196",     "msp430f47167",
1933       "msp430f47177",     "msp430f47187",     "msp430f47197"
1934     };
1935   int i;
1936 
1937   if (msp430_hwmult_type == LARGE)
1938     return true;
1939 
1940   if (target_mcu == NULL || msp430_hwmult_type != AUTO)
1941     return false;
1942 
1943   for (i = ARRAY_SIZE (known_32bit_mult_mcus); i--;)
1944     if (strcasecmp (target_mcu, known_32bit_mult_mcus[i]) == 0)
1945       return true;
1946 
1947   return false;
1948 }
1949 
1950 /* This function does the same as the default, but it will replace GCC
1951    function names with the MSPABI-specified ones.  */
1952 void
msp430_output_labelref(FILE * file,const char * name)1953 msp430_output_labelref (FILE *file, const char *name)
1954 {
1955   int i;
1956 
1957   for (i = 0; helper_function_name_mappings [i].gcc_name; i++)
1958     if (strcmp (helper_function_name_mappings [i].gcc_name, name) == 0)
1959       {
1960 	name = helper_function_name_mappings [i].ti_name;
1961 	break;
1962       }
1963 
1964   /* If we have been given a specific MCU name then we may be
1965      able to make use of its hardware multiply capabilities.  */
1966   if (msp430_hwmult_type != NONE)
1967     {
1968       if (strcmp ("__mspabi_mpyi", name) == 0)
1969 	{
1970 	  if (msp430_use_f5_series_hwmult ())
1971 	    name = "__mulhi2_f5";
1972 	  else
1973 	    name = "__mulhi2";
1974 	}
1975       else if (strcmp ("__mspabi_mpyl", name) == 0)
1976 	{
1977 	  if (msp430_use_f5_series_hwmult ())
1978 	    name = "__mulsi2_f5";
1979 	  else if (use_32bit_hwmult ())
1980 	    name = "__mulsi2_hw32";
1981 	  else
1982 	    name = "__mulsi2";
1983 	}
1984     }
1985 
1986   fputs (name, file);
1987 }
1988 
1989 /* Common code for msp430_print_operand...  */
1990 
1991 static void
msp430_print_operand_raw(FILE * file,rtx op)1992 msp430_print_operand_raw (FILE * file, rtx op)
1993 {
1994   HOST_WIDE_INT i;
1995 
1996   switch (GET_CODE (op))
1997     {
1998     case REG:
1999       fprintf (file, "%s", reg_names [REGNO (op)]);
2000       break;
2001 
2002     case CONST_INT:
2003       i = INTVAL (op);
2004       if (TARGET_ASM_HEX)
2005 	fprintf (file, "%#" HOST_WIDE_INT_PRINT "x", i);
2006       else
2007 	fprintf (file, "%" HOST_WIDE_INT_PRINT "d", i);
2008       break;
2009 
2010     case CONST:
2011     case PLUS:
2012     case MINUS:
2013     case SYMBOL_REF:
2014     case LABEL_REF:
2015       output_addr_const (file, op);
2016       break;
2017 
2018     default:
2019       print_rtl (file, op);
2020       break;
2021     }
2022 }
2023 
2024 #undef  TARGET_PRINT_OPERAND_ADDRESS
2025 #define TARGET_PRINT_OPERAND_ADDRESS	msp430_print_operand_addr
2026 
2027 /* Output to stdio stream FILE the assembler syntax for an
2028    instruction operand that is a memory reference whose address
2029    is ADDR.  */
2030 
2031 static void
msp430_print_operand_addr(FILE * file,rtx addr)2032 msp430_print_operand_addr (FILE * file, rtx addr)
2033 {
2034   switch (GET_CODE (addr))
2035     {
2036     case PLUS:
2037       msp430_print_operand_raw (file, XEXP (addr, 1));
2038       gcc_assert (REG_P (XEXP (addr, 0)));
2039       fprintf (file, "(%s)", reg_names [REGNO (XEXP (addr, 0))]);
2040       return;
2041 
2042     case REG:
2043       fprintf (file, "@");
2044       break;
2045 
2046     case CONST:
2047     case CONST_INT:
2048     case SYMBOL_REF:
2049     case LABEL_REF:
2050       fprintf (file, "&");
2051       break;
2052 
2053     default:
2054       break;
2055     }
2056 
2057   msp430_print_operand_raw (file, addr);
2058 }
2059 
2060 #undef  TARGET_PRINT_OPERAND
2061 #define TARGET_PRINT_OPERAND		msp430_print_operand
2062 
2063 /* A   low 16-bits of int/lower of register pair
2064    B   high 16-bits of int/higher of register pair
2065    C   bits 32-47 of a 64-bit value/reg 3 of a DImode value
2066    D   bits 48-63 of a 64-bit value/reg 4 of a DImode value
2067    H   like %B (for backwards compatibility)
2068    I   inverse of value
2069    J   an integer without a # prefix
2070    L   like %A (for backwards compatibility)
2071    O   offset of the top of the stack
2072    Q   like X but generates an A postfix
2073    R   inverse of condition code, unsigned.
2074    X   X instruction postfix in large mode
2075    Y   value - 4
2076    Z   value - 1
2077    b   .B or .W or .A, depending upon the mode
2078    p   bit position
2079    r   inverse of condition code
2080    x   like X but only for pointers.  */
2081 
2082 static void
msp430_print_operand(FILE * file,rtx op,int letter)2083 msp430_print_operand (FILE * file, rtx op, int letter)
2084 {
2085   rtx addr;
2086 
2087   /* We can't use c, n, a, or l.  */
2088   switch (letter)
2089     {
2090     case 'Z':
2091       gcc_assert (CONST_INT_P (op));
2092       /* Print the constant value, less one.  */
2093       fprintf (file, "#%ld", INTVAL (op) - 1);
2094       return;
2095     case 'Y':
2096       gcc_assert (CONST_INT_P (op));
2097       /* Print the constant value, less four.  */
2098       fprintf (file, "#%ld", INTVAL (op) - 4);
2099       return;
2100     case 'I':
2101       if (GET_CODE (op) == CONST_INT)
2102 	{
2103 	  /* Inverse of constants */
2104 	  int i = INTVAL (op);
2105 	  fprintf (file, "%d", ~i);
2106 	  return;
2107 	}
2108       op = XEXP (op, 0);
2109       break;
2110     case 'r': /* Conditional jump where the condition is reversed.  */
2111       switch (GET_CODE (op))
2112 	{
2113 	case EQ: fprintf (file, "NE"); break;
2114 	case NE: fprintf (file, "EQ"); break;
2115 	case GEU: fprintf (file, "LO"); break;
2116 	case LTU: fprintf (file, "HS"); break;
2117 	case GE: fprintf (file, "L"); break;
2118 	case LT: fprintf (file, "GE"); break;
2119 	  /* Assume these have reversed operands.  */
2120 	case GTU: fprintf (file, "HS"); break;
2121 	case LEU: fprintf (file, "LO"); break;
2122 	case GT: fprintf (file, "GE"); break;
2123 	case LE: fprintf (file, "L"); break;
2124 	default:
2125 	  msp430_print_operand_raw (file, op);
2126 	  break;
2127 	}
2128       return;
2129     case 'R': /* Conditional jump where the operands are reversed.  */
2130       switch (GET_CODE (op))
2131 	{
2132 	case GTU: fprintf (file, "LO"); break;
2133 	case LEU: fprintf (file, "HS"); break;
2134 	case GT: fprintf (file, "L"); break;
2135 	case LE: fprintf (file, "GE"); break;
2136 	default:
2137 	  msp430_print_operand_raw (file, op);
2138 	  break;
2139 	}
2140       return;
2141     case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc.  */
2142       gcc_assert (CONST_INT_P (op));
2143       fprintf (file, "#%d", 1 << INTVAL (op));
2144       return;
2145     case 'b':
2146       switch (GET_MODE (op))
2147 	{
2148 	case QImode: fprintf (file, ".B"); return;
2149 	case HImode: fprintf (file, ".W"); return;
2150 	case PSImode: fprintf (file, ".A"); return;
2151 	case SImode: fprintf (file, ".A"); return;
2152 	default:
2153 	  return;
2154 	}
2155     case 'A':
2156     case 'L': /* Low half.  */
2157       switch (GET_CODE (op))
2158 	{
2159 	case MEM:
2160 	  op = adjust_address (op, Pmode, 0);
2161 	  break;
2162 	case REG:
2163 	  break;
2164 	case CONST_INT:
2165 	  op = GEN_INT (INTVAL (op) & 0xffff);
2166 	  letter = 0;
2167 	  break;
2168 	default:
2169 	  /* If you get here, figure out a test case :-) */
2170 	  gcc_unreachable ();
2171 	}
2172       break;
2173     case 'B':
2174     case 'H': /* high half */
2175       switch (GET_CODE (op))
2176 	{
2177 	case MEM:
2178 	  op = adjust_address (op, Pmode, 2);
2179 	  break;
2180 	case REG:
2181 	  op = gen_rtx_REG (Pmode, REGNO (op) + 1);
2182 	  break;
2183 	case CONST_INT:
2184 	  op = GEN_INT (INTVAL (op) >> 16);
2185 	  letter = 0;
2186 	  break;
2187 	default:
2188 	  /* If you get here, figure out a test case :-) */
2189 	  gcc_unreachable ();
2190 	}
2191       break;
2192     case 'C':
2193       switch (GET_CODE (op))
2194 	{
2195 	case MEM:
2196 	  op = adjust_address (op, Pmode, 3);
2197 	  break;
2198 	case REG:
2199 	  op = gen_rtx_REG (Pmode, REGNO (op) + 2);
2200 	  break;
2201 	case CONST_INT:
2202 	  op = GEN_INT ((long long) INTVAL (op) >> 32);
2203 	  letter = 0;
2204 	  break;
2205 	default:
2206 	  /* If you get here, figure out a test case :-) */
2207 	  gcc_unreachable ();
2208 	}
2209       break;
2210     case 'D':
2211       switch (GET_CODE (op))
2212 	{
2213 	case MEM:
2214 	  op = adjust_address (op, Pmode, 4);
2215 	  break;
2216 	case REG:
2217 	  op = gen_rtx_REG (Pmode, REGNO (op) + 3);
2218 	  break;
2219 	case CONST_INT:
2220 	  op = GEN_INT ((long long) INTVAL (op) >> 48);
2221 	  letter = 0;
2222 	  break;
2223 	default:
2224 	  /* If you get here, figure out a test case :-) */
2225 	  gcc_unreachable ();
2226 	}
2227       break;
2228 
2229     case 'X':
2230       /* This is used to turn, for example, an ADD opcode into an ADDX
2231 	 opcode when we're using 20-bit addresses.  */
2232       if (TARGET_LARGE)
2233 	fprintf (file, "X");
2234       /* We don't care which operand we use, but we want 'X' in the MD
2235 	 file, so we do it this way.  */
2236       return;
2237 
2238     case 'x':
2239       /* Similarly, but only for PSImodes.  BIC, for example, needs this.  */
2240       if (TARGET_LARGE && GET_MODE (op) == PSImode)
2241 	fprintf (file, "X");
2242       return;
2243 
2244     case 'Q':
2245       /* Likewise, for BR -> BRA.  */
2246       if (TARGET_LARGE)
2247 	fprintf (file, "A");
2248       return;
2249 
2250     case 'O':
2251       /* Computes the offset to the top of the stack for the current frame.
2252 	 This has to be done here rather than in, say, msp430_expand_builtin()
2253 	 because builtins are expanded before the frame layout is determined.  */
2254       fprintf (file, "%d",
2255 	       msp430_initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM)
2256 	       - (TARGET_LARGE ? 4 : 2));
2257       return;
2258 
2259     case 'J':
2260       gcc_assert (GET_CODE (op) == CONST_INT);
2261     case 0:
2262       break;
2263     default:
2264       output_operand_lossage ("invalid operand prefix");
2265       return;
2266     }
2267 
2268   switch (GET_CODE (op))
2269     {
2270     case REG:
2271       msp430_print_operand_raw (file, op);
2272       break;
2273 
2274     case MEM:
2275       addr = XEXP (op, 0);
2276       msp430_print_operand_addr (file, addr);
2277       break;
2278 
2279     case CONST:
2280       if (GET_CODE (XEXP (op, 0)) == ZERO_EXTRACT)
2281 	{
2282 	  op = XEXP (op, 0);
2283 	  switch (INTVAL (XEXP (op, 2)))
2284 	    {
2285 	    case 0:
2286 	      fprintf (file, "#lo (");
2287 	      msp430_print_operand_raw (file, XEXP (op, 0));
2288 	      fprintf (file, ")");
2289 	      break;
2290 
2291 	    case 16:
2292 	      fprintf (file, "#hi (");
2293 	      msp430_print_operand_raw (file, XEXP (op, 0));
2294 	      fprintf (file, ")");
2295 	      break;
2296 
2297 	    default:
2298 	      output_operand_lossage ("invalid zero extract");
2299 	      break;
2300 	    }
2301 	  break;
2302 	}
2303       /* Fall through.  */
2304     case CONST_INT:
2305     case SYMBOL_REF:
2306     case LABEL_REF:
2307       if (letter == 0)
2308 	fprintf (file, "#");
2309       msp430_print_operand_raw (file, op);
2310       break;
2311 
2312     case EQ: fprintf (file, "EQ"); break;
2313     case NE: fprintf (file, "NE"); break;
2314     case GEU: fprintf (file, "HS"); break;
2315     case LTU: fprintf (file, "LO"); break;
2316     case GE: fprintf (file, "GE"); break;
2317     case LT: fprintf (file, "L"); break;
2318 
2319     default:
2320       print_rtl (file, op);
2321       break;
2322     }
2323 }
2324 
2325 
2326 /* Frame stuff.  */
2327 
2328 rtx
msp430_return_addr_rtx(int count)2329 msp430_return_addr_rtx (int count)
2330 {
2331   int ra_size;
2332   if (count)
2333     return NULL_RTX;
2334 
2335   ra_size = TARGET_LARGE ? 4 : 2;
2336   if (crtl->args.pretend_args_size)
2337     ra_size += 2;
2338 
2339   return gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, arg_pointer_rtx, GEN_INT (- ra_size)));
2340 }
2341 
2342 rtx
msp430_incoming_return_addr_rtx(void)2343 msp430_incoming_return_addr_rtx (void)
2344 {
2345   return gen_rtx_MEM (Pmode, stack_pointer_rtx);
2346 }
2347 
2348 /* Instruction generation stuff.  */
2349 
2350 /* Generate a sequence of instructions to sign-extend an HI
2351    value into an SI value.  Handles the tricky case where
2352    we are overwriting the destination.  */
2353 
2354 const char *
msp430x_extendhisi(rtx * operands)2355 msp430x_extendhisi (rtx * operands)
2356 {
2357   if (REGNO (operands[0]) == REGNO (operands[1]))
2358     /* Low word of dest == source word.  */
2359     return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes.  */
2360 
2361   if (! msp430x)
2362     /* Note: This sequence is approximately the same length as invoking a helper
2363        function to perform the sign-extension, as in:
2364 
2365          MOV.W  %1, %L0
2366 	 MOV.W  %1, r12
2367 	 CALL   __mspabi_srai_15
2368 	 MOV.W  r12, %H0
2369 
2370        but this version does not involve any function calls or using argument
2371        registers, so it reduces register pressure.  */
2372     return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes.  */
2373 
2374   if (REGNO (operands[0]) + 1 == REGNO (operands[1]))
2375     /* High word of dest == source word.  */
2376     return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes.  */
2377 
2378   /* No overlap between dest and source.  */
2379   return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes.  */
2380 }
2381 
2382 /* Likewise for logical right shifts.  */
2383 const char *
msp430x_logical_shift_right(rtx amount)2384 msp430x_logical_shift_right (rtx amount)
2385 {
2386   /* The MSP430X's logical right shift instruction - RRUM - does
2387      not use an extension word, so we cannot encode a repeat count.
2388      Try various alternatives to work around this.  If the count
2389      is in a register we are stuck, hence the assert.  */
2390   gcc_assert (CONST_INT_P (amount));
2391 
2392   if (INTVAL (amount) <= 0
2393       || INTVAL (amount) >= 16)
2394     return "# nop logical shift.";
2395 
2396   if (INTVAL (amount) > 0
2397       && INTVAL (amount) < 5)
2398     return "rrum.w\t%2, %0"; /* Two bytes.  */
2399 
2400   if (INTVAL (amount) > 4
2401       && INTVAL (amount) < 9)
2402     return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes.  */
2403 
2404   /* First we logically shift right by one.  Now we know
2405      that the top bit is zero and we can use the arithmetic
2406      right shift instruction to perform the rest of the shift.  */
2407   return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes.  */
2408 }
2409 
2410 struct gcc_target targetm = TARGET_INITIALIZER;
2411 
2412 #include "gt-msp430.h"
2413