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