Merged revisions 208012,208018-208019,208021,208023-208030,208033,208037,208040-20804...
[official-gcc.git] / main / gcc / config / msp430 / msp430.c
blob80a17a6e31e3ffdc8f510086919f2910bf61218f
1 /* Subroutines used for code generation on TI MSP430 processors.
2 Copyright (C) 2012-2014 Free Software Foundation, Inc.
3 Contributed by Red Hat.
5 This file is part of GCC.
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.
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.
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/>. */
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"
56 static void msp430_compute_frame_info (void);
60 /* Run-time Target Specification. */
62 bool msp430x = true;
64 struct GTY(()) machine_function
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];
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;
81 /* How much we adjust the stack when returning from an exception
82 handler. */
83 rtx eh_stack_adjust;
86 /* This is our init_machine_status, as set in
87 msp_option_override. */
88 static struct machine_function *
89 msp430_init_machine_status (void)
91 struct machine_function *m;
93 m = ggc_alloc_cleared_machine_function ();
95 return m;
98 #undef TARGET_HANDLE_OPTION
99 #define TARGET_HANDLE_OPTION msp430_handle_option
101 bool
102 msp430_handle_option (struct gcc_options *opts ATTRIBUTE_UNUSED,
103 struct gcc_options *opts_set ATTRIBUTE_UNUSED,
104 const struct cl_decoded_option *decoded ATTRIBUTE_UNUSED,
105 location_t loc ATTRIBUTE_UNUSED)
107 return true;
110 #undef TARGET_OPTION_OVERRIDE
111 #define TARGET_OPTION_OVERRIDE msp430_option_override
113 static const char * msp430_mcu_names [] =
115 "msp430afe221", "msp430afe222", "msp430afe223", "msp430afe231",
116 "msp430afe232", "msp430afe233", "msp430afe251", "msp430afe252",
117 "msp430afe253", "msp430c091", "msp430c092", "msp430c111",
118 "msp430c1111", "msp430c112", "msp430c1121", "msp430c1331",
119 "msp430c1351", "msp430c311s", "msp430c312", "msp430c313",
120 "msp430c314", "msp430c315", "msp430c323", "msp430c325",
121 "msp430c336", "msp430c337", "msp430c412", "msp430c413",
122 "msp430e112", "msp430e313", "msp430e315", "msp430e325",
123 "msp430e337", "msp430f110", "msp430f1101", "msp430f1101a",
124 "msp430f1111", "msp430f1111a", "msp430f112", "msp430f1121",
125 "msp430f1121a", "msp430f1122", "msp430f1132", "msp430f122",
126 "msp430f1222", "msp430f123", "msp430f1232", "msp430f133",
127 "msp430f135", "msp430f147", "msp430f1471", "msp430f148",
128 "msp430f1481", "msp430f149", "msp430f1491", "msp430f155",
129 "msp430f156", "msp430f157", "msp430f1610", "msp430f1611",
130 "msp430f1612", "msp430f167", "msp430f168", "msp430f169",
131 "msp430f2001", "msp430f2002", "msp430f2003", "msp430f2011",
132 "msp430f2012", "msp430f2013", "msp430f2101", "msp430f2111",
133 "msp430f2112", "msp430f2121", "msp430f2122", "msp430f2131",
134 "msp430f2132", "msp430f2232", "msp430f2234", "msp430f2252",
135 "msp430f2254", "msp430f2272", "msp430f2274", "msp430f233",
136 "msp430f2330", "msp430f235", "msp430f2350", "msp430f2370",
137 "msp430f2410", "msp430f247", "msp430f2471", "msp430f248",
138 "msp430f2481", "msp430f249", "msp430f2491", "msp430f412",
139 "msp430f413", "msp430f4132", "msp430f415", "msp430f4152",
140 "msp430f417", "msp430f423", "msp430f423a", "msp430f425",
141 "msp430f4250", "msp430f425a", "msp430f4260", "msp430f427",
142 "msp430f4270", "msp430f427a", "msp430f435", "msp430f4351",
143 "msp430f436", "msp430f4361", "msp430f437", "msp430f4371",
144 "msp430f438", "msp430f439", "msp430f447", "msp430f448",
145 "msp430f4481", "msp430f449", "msp430f4491", "msp430f477",
146 "msp430f478", "msp430f4783", "msp430f4784", "msp430f479",
147 "msp430f4793", "msp430f4794", "msp430fe423", "msp430fe4232",
148 "msp430fe423a", "msp430fe4242", "msp430fe425", "msp430fe4252",
149 "msp430fe425a", "msp430fe427", "msp430fe4272", "msp430fe427a",
150 "msp430fg4250", "msp430fg4260", "msp430fg4270", "msp430fg437",
151 "msp430fg438", "msp430fg439", "msp430fg477", "msp430fg478",
152 "msp430fg479", "msp430fw423", "msp430fw425", "msp430fw427",
153 "msp430fw428", "msp430fw429", "msp430g2001", "msp430g2101",
154 "msp430g2102", "msp430g2111", "msp430g2112", "msp430g2113",
155 "msp430g2121", "msp430g2131", "msp430g2132", "msp430g2152",
156 "msp430g2153", "msp430g2201", "msp430g2202", "msp430g2203",
157 "msp430g2210", "msp430g2211", "msp430g2212", "msp430g2213",
158 "msp430g2221", "msp430g2230", "msp430g2231", "msp430g2232",
159 "msp430g2233", "msp430g2252", "msp430g2253", "msp430g2302",
160 "msp430g2303", "msp430g2312", "msp430g2313", "msp430g2332",
161 "msp430g2333", "msp430g2352", "msp430g2353", "msp430g2402",
162 "msp430g2403", "msp430g2412", "msp430g2413", "msp430g2432",
163 "msp430g2433", "msp430g2444", "msp430g2452", "msp430g2453",
164 "msp430g2513", "msp430g2533", "msp430g2544", "msp430g2553",
165 "msp430g2744", "msp430g2755", "msp430g2855", "msp430g2955",
166 "msp430i2020", "msp430i2021", "msp430i2030", "msp430i2031",
167 "msp430i2040", "msp430i2041", "msp430l092", "msp430p112",
168 "msp430p313", "msp430p315", "msp430p315s", "msp430p325",
169 "msp430p337", "msp430tch5e"
172 /* Generate a C preprocessor symbol based upon the MCU selected by the user.
173 If a specific MCU has not been selected then return a generic symbol instead. */
175 const char *
176 msp430_mcu_name (void)
178 if (target_mcu)
180 unsigned int i;
181 static char mcu_name [64];
183 snprintf (mcu_name, sizeof (mcu_name) - 1, "__%s__", target_mcu);
184 for (i = strlen (mcu_name); i--;)
185 mcu_name[i] = TOUPPER (mcu_name[i]);
186 return mcu_name;
189 return msp430x ? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
192 static void
193 msp430_option_override (void)
195 init_machine_status = msp430_init_machine_status;
197 if (target_cpu)
199 if (strcasecmp (target_cpu, "msp430x") == 0
200 || strcasecmp (target_cpu, "msp430xv2") == 0
201 || strcasecmp (target_cpu, "430x") == 0
202 || strcasecmp (target_cpu, "430xv2") == 0)
203 msp430x = true;
204 else if (strcasecmp (target_cpu, "msp430") == 0
205 || strcasecmp (target_cpu, "430") == 0)
206 msp430x = false;
207 else
208 error ("unrecognised argument of -mcpu: %s", target_cpu);
211 if (target_mcu)
213 int i;
215 /* If we are given an MCU name, we assume that it supports 430X.
216 Then we check to see if it is one of the known MCUs that only
217 supports 430. */
218 msp430x = true;
220 /* For backwards compatibility we recognise two generic MCU
221 430X names. However we want to be able to generate special C
222 preprocessor defines for them, which is why we set target_mcu
223 to NULL. */
224 if (strcasecmp (target_mcu, "msp430") == 0)
226 msp430x = false;
227 target_mcu = NULL;
229 else if (strcasecmp (target_mcu, "msp430x") == 0
230 || strcasecmp (target_mcu, "msp430xv2") == 0)
231 target_mcu = NULL;
232 else
233 for (i = ARRAY_SIZE (msp430_mcu_names); i--;)
234 if (strcasecmp (msp430_mcu_names[i], target_mcu) == 0)
236 msp430x = false;
237 break;
239 /* It is not an error if we do not match the MCU name. There are
240 hundreds of them. */
243 if (TARGET_LARGE && !msp430x)
244 error ("-mlarge requires a 430X-compatible -mmcu=");
246 if (flag_exceptions || flag_non_call_exceptions
247 || flag_unwind_tables || flag_asynchronous_unwind_tables)
248 flag_omit_frame_pointer = false;
249 else
250 flag_omit_frame_pointer = true;
252 /* This is a hack to work around a problem with the newlib build
253 mechanism. Newlib always appends CFLAGS to the end of the GCC
254 command line and always sets -O2 in CFLAGS. Thus it is not
255 possible to build newlib with -Os enabled. Until now... */
256 if (TARGET_OPT_SPACE && optimize < 3)
257 optimize_size = 1;
262 /* Storage Layout */
264 #undef TARGET_MS_BITFIELD_LAYOUT_P
265 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
267 bool
268 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED)
270 return false;
275 /* Register Usage */
277 /* Implements HARD_REGNO_NREGS. MSP430X registers can hold a single
278 PSImode value, but not an SImode value. */
280 msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED,
281 enum machine_mode mode)
283 if (mode == PSImode && msp430x)
284 return 1;
285 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
286 / UNITS_PER_WORD);
289 /* Implements HARD_REGNO_MODE_OK. */
291 msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED,
292 enum machine_mode mode)
294 return regno <= (ARG_POINTER_REGNUM - msp430_hard_regno_nregs (regno, mode));
297 /* Implements MODES_TIEABLE_P. */
298 bool
299 msp430_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
301 if ((mode1 == PSImode || mode2 == SImode)
302 || (mode1 == SImode || mode2 == PSImode))
303 return false;
305 return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
306 || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
307 == (GET_MODE_CLASS (mode2) == MODE_FLOAT
308 || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
311 #undef TARGET_FRAME_POINTER_REQUIRED
312 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
314 static bool
315 msp430_frame_pointer_required (void)
317 return false;
320 #undef TARGET_CAN_ELIMINATE
321 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
323 static bool
324 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED,
325 const int to_reg ATTRIBUTE_UNUSED)
327 return true;
330 /* Implements INITIAL_ELIMINATION_OFFSET. */
332 msp430_initial_elimination_offset (int from, int to)
334 int rv = 0; /* As if arg to arg. */
336 msp430_compute_frame_info ();
338 switch (to)
340 case STACK_POINTER_REGNUM:
341 rv += cfun->machine->framesize_outgoing;
342 rv += cfun->machine->framesize_locals;
343 /* Fall through. */
344 case FRAME_POINTER_REGNUM:
345 rv += cfun->machine->framesize_regs;
346 /* Allow for the saved return address. */
347 rv += (TARGET_LARGE ? 4 : 2);
348 /* NB/ No need to allow for crtl->args.pretend_args_size.
349 GCC does that for us. */
350 break;
351 default:
352 gcc_unreachable ();
355 switch (from)
357 case FRAME_POINTER_REGNUM:
358 /* Allow for the fall through above. */
359 rv -= (TARGET_LARGE ? 4 : 2);
360 rv -= cfun->machine->framesize_regs;
361 case ARG_POINTER_REGNUM:
362 break;
363 default:
364 gcc_unreachable ();
367 return rv;
370 /* Named Address Space support */
373 /* Return the appropriate mode for a named address pointer. */
374 #undef TARGET_ADDR_SPACE_POINTER_MODE
375 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
376 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
377 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
379 static enum machine_mode
380 msp430_addr_space_pointer_mode (addr_space_t addrspace)
382 switch (addrspace)
384 default:
385 case ADDR_SPACE_GENERIC:
386 return Pmode;
387 case ADDR_SPACE_NEAR:
388 return HImode;
389 case ADDR_SPACE_FAR:
390 return PSImode;
394 /* Function pointers are stored in unwind_word sized
395 variables, so make sure that unwind_word is big enough. */
396 #undef TARGET_UNWIND_WORD_MODE
397 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
399 static enum machine_mode
400 msp430_unwind_word_mode (void)
402 return TARGET_LARGE ? SImode : HImode;
405 /* Determine if one named address space is a subset of another. */
406 #undef TARGET_ADDR_SPACE_SUBSET_P
407 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
408 static bool
409 msp430_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
411 if (subset == superset)
412 return true;
413 else
414 return (subset != ADDR_SPACE_FAR && superset == ADDR_SPACE_FAR);
417 #undef TARGET_ADDR_SPACE_CONVERT
418 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
419 /* Convert from one address space to another. */
420 static rtx
421 msp430_addr_space_convert (rtx op, tree from_type, tree to_type)
423 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
424 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
425 rtx result;
427 if (to_as != ADDR_SPACE_FAR && from_as == ADDR_SPACE_FAR)
429 /* This is unpredictable, as we're truncating off usable address
430 bits. */
432 if (CONSTANT_P (op))
433 return gen_rtx_CONST (HImode, op);
435 result = gen_reg_rtx (HImode);
436 emit_insn (gen_truncpsihi2 (result, op));
437 return result;
439 else if (to_as == ADDR_SPACE_FAR && from_as != ADDR_SPACE_FAR)
441 /* This always works. */
443 if (CONSTANT_P (op))
444 return gen_rtx_CONST (PSImode, op);
446 result = gen_reg_rtx (PSImode);
447 emit_insn (gen_zero_extendhipsi2 (result, op));
448 return result;
450 else
451 gcc_unreachable ();
454 /* Stack Layout and Calling Conventions. */
456 /* For each function, we list the gcc version and the TI version on
457 each line, where we're converting the function names. */
458 static char const * const special_convention_function_names [] =
460 "__muldi3", "__mspabi_mpyll",
461 "__udivdi3", "__mspabi_divull",
462 "__umoddi3", "__mspabi_remull",
463 "__divdi3", "__mspabi_divlli",
464 "__moddi3", "__mspabi_remlli",
465 "__mspabi_srall",
466 "__mspabi_srlll",
467 "__mspabi_sllll",
468 "__adddf3", "__mspabi_addd",
469 "__subdf3", "__mspabi_subd",
470 "__muldf3", "__mspabi_mpyd",
471 "__divdf3", "__mspabi_divd",
472 "__mspabi_cmpd",
473 NULL
476 /* TRUE if the function passed is a "speical" function. Special
477 functions pass two DImode parameters in registers. */
478 static bool
479 msp430_special_register_convention_p (const char *name)
481 int i;
483 for (i = 0; special_convention_function_names [i]; i++)
484 if (! strcmp (name, special_convention_function_names [i]))
485 return true;
487 return false;
490 #undef TARGET_FUNCTION_VALUE_REGNO_P
491 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
493 bool
494 msp430_function_value_regno_p (unsigned int regno)
496 return regno == 12;
500 #undef TARGET_FUNCTION_VALUE
501 #define TARGET_FUNCTION_VALUE msp430_function_value
504 msp430_function_value (const_tree ret_type,
505 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
506 bool outgoing ATTRIBUTE_UNUSED)
508 return gen_rtx_REG (TYPE_MODE (ret_type), 12);
511 #undef TARGET_LIBCALL_VALUE
512 #define TARGET_LIBCALL_VALUE msp430_libcall_value
515 msp430_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
517 return gen_rtx_REG (mode, 12);
520 /* Implements INIT_CUMULATIVE_ARGS. */
521 void
522 msp430_init_cumulative_args (CUMULATIVE_ARGS *ca,
523 tree fntype ATTRIBUTE_UNUSED,
524 rtx libname ATTRIBUTE_UNUSED,
525 tree fndecl ATTRIBUTE_UNUSED,
526 int n_named_args ATTRIBUTE_UNUSED)
528 const char *fname;
529 memset (ca, 0, sizeof(*ca));
531 ca->can_split = 1;
533 if (fndecl)
534 fname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
535 else if (libname)
536 fname = XSTR (libname, 0);
537 else
538 fname = NULL;
540 if (fname && msp430_special_register_convention_p (fname))
541 ca->special_p = 1;
544 /* Helper function for argument passing; this function is the common
545 code that determines where an argument will be passed. */
546 static void
547 msp430_evaluate_arg (cumulative_args_t cap,
548 enum machine_mode mode,
549 const_tree type ATTRIBUTE_UNUSED,
550 bool named)
552 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
553 int nregs = GET_MODE_SIZE (mode);
554 int i;
556 ca->reg_count = 0;
557 ca->mem_count = 0;
559 if (!named)
560 return;
562 if (mode == PSImode)
563 nregs = 1;
564 else
565 nregs = (nregs + 1) / 2;
567 if (ca->special_p)
569 /* Function is passed two DImode operands, in R8:R11 and
570 R12:15. */
571 ca->start_reg = 8;
572 ca->reg_count = 4;
573 return;
576 switch (nregs)
578 case 1:
579 for (i = 0; i < 4; i++)
580 if (! ca->reg_used [i])
582 ca->reg_count = 1;
583 ca->start_reg = CA_FIRST_REG + i;
584 return;
586 break;
587 case 2:
588 for (i = 0; i < 3; i++)
589 if (! ca->reg_used [i] && ! ca->reg_used [i + 1])
591 ca->reg_count = 2;
592 ca->start_reg = CA_FIRST_REG + i;
593 return;
595 if (! ca->reg_used [3] && ca->can_split)
597 ca->reg_count = 1;
598 ca->mem_count = 2;
599 ca->start_reg = CA_FIRST_REG + 3;
600 return;
602 break;
603 case 3:
604 case 4:
605 ca->can_split = 0;
606 if (! ca->reg_used [0]
607 && ! ca->reg_used [1]
608 && ! ca->reg_used [2]
609 && ! ca->reg_used [3])
611 ca->reg_count = 4;
612 ca->start_reg = CA_FIRST_REG;
613 return;
615 break;
619 #undef TARGET_PROMOTE_PROTOTYPES
620 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
622 bool
623 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED)
625 return false;
628 #undef TARGET_FUNCTION_ARG
629 #define TARGET_FUNCTION_ARG msp430_function_arg
632 msp430_function_arg (cumulative_args_t cap,
633 enum machine_mode mode,
634 const_tree type,
635 bool named)
637 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
639 msp430_evaluate_arg (cap, mode, type, named);
641 if (ca->reg_count)
642 return gen_rtx_REG (mode, ca->start_reg);
644 return 0;
647 #undef TARGET_ARG_PARTIAL_BYTES
648 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
651 msp430_arg_partial_bytes (cumulative_args_t cap,
652 enum machine_mode mode,
653 tree type,
654 bool named)
656 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
658 msp430_evaluate_arg (cap, mode, type, named);
660 if (ca->reg_count && ca->mem_count)
661 return ca->reg_count * UNITS_PER_WORD;
663 return 0;
666 #undef TARGET_PASS_BY_REFERENCE
667 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
669 static bool
670 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED,
671 enum machine_mode mode,
672 const_tree type,
673 bool named ATTRIBUTE_UNUSED)
675 return (mode == BLKmode
676 || (type && TREE_CODE (type) == RECORD_TYPE)
677 || (type && TREE_CODE (type) == UNION_TYPE));
680 #undef TARGET_CALLEE_COPIES
681 #define TARGET_CALLEE_COPIES msp430_callee_copies
683 static bool
684 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED,
685 enum machine_mode mode ATTRIBUTE_UNUSED,
686 const_tree type ATTRIBUTE_UNUSED,
687 bool named ATTRIBUTE_UNUSED)
689 return true;
692 #undef TARGET_FUNCTION_ARG_ADVANCE
693 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
695 void
696 msp430_function_arg_advance (cumulative_args_t cap,
697 enum machine_mode mode,
698 const_tree type,
699 bool named)
701 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
702 int i;
704 msp430_evaluate_arg (cap, mode, type, named);
706 if (ca->start_reg >= CA_FIRST_REG)
707 for (i = 0; i < ca->reg_count; i ++)
708 ca->reg_used [i + ca->start_reg - CA_FIRST_REG] = 1;
710 ca->special_p = 0;
713 #undef TARGET_FUNCTION_ARG_BOUNDARY
714 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
716 static unsigned int
717 msp430_function_arg_boundary (enum machine_mode mode, const_tree type)
719 if (mode == BLKmode
720 && int_size_in_bytes (type) > 1)
721 return 16;
722 if (GET_MODE_BITSIZE (mode) > 8)
723 return 16;
724 return 8;
727 #undef TARGET_RETURN_IN_MEMORY
728 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
730 static bool
731 msp430_return_in_memory (const_tree ret_type, const_tree fntype ATTRIBUTE_UNUSED)
733 enum machine_mode mode = TYPE_MODE (ret_type);
735 if (mode == BLKmode
736 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == RECORD_TYPE)
737 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == UNION_TYPE))
738 return true;
740 if (GET_MODE_SIZE (mode) > 8)
741 return true;
743 return false;
746 #undef TARGET_GET_RAW_ARG_MODE
747 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
749 static enum machine_mode
750 msp430_get_raw_arg_mode (int regno)
752 return (regno == ARG_POINTER_REGNUM) ? VOIDmode : Pmode;
755 #undef TARGET_GET_RAW_RESULT_MODE
756 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
758 static enum machine_mode
759 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED)
761 return Pmode;
764 /* Addressing Modes */
766 #undef TARGET_LEGITIMATE_ADDRESS_P
767 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
769 static bool
770 reg_ok_for_addr (rtx r, bool strict)
772 int rn = REGNO (r);
774 if (strict && rn >= FIRST_PSEUDO_REGISTER)
775 rn = reg_renumber [rn];
776 if (strict && 0 <= rn && rn < FIRST_PSEUDO_REGISTER)
777 return true;
778 if (!strict)
779 return true;
780 return false;
783 bool
784 msp430_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
785 rtx x ATTRIBUTE_UNUSED,
786 bool strict ATTRIBUTE_UNUSED)
788 switch (GET_CODE (x))
790 case MEM:
791 return false;
793 case PLUS:
794 if (REG_P (XEXP (x, 0)))
796 if (GET_MODE (x) != GET_MODE (XEXP (x, 0)))
797 return false;
798 if (!reg_ok_for_addr (XEXP (x, 0), strict))
799 return false;
800 switch (GET_CODE (XEXP (x, 1)))
802 case CONST:
803 case SYMBOL_REF:
804 case CONST_INT:
805 return true;
806 default:
807 return false;
810 return false;
812 case REG:
813 if (!reg_ok_for_addr (x, strict))
814 return false;
815 /* else... */
816 case CONST:
817 case SYMBOL_REF:
818 case CONST_INT:
819 return true;
821 default:
822 return false;
826 #undef TARGET_LEGITIMATE_CONSTANT_P
827 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
829 static bool
830 msp430_legitimate_constant (enum machine_mode mode, rtx x)
832 return ! CONST_INT_P (x)
833 || mode != PSImode
834 /* GCC does not know the width of the PSImode, so make
835 sure that it does not try to use a constant value that
836 is out of range. */
837 || (INTVAL (x) < (1 << 20) && INTVAL (x) >= (-1 << 20));
841 #undef TARGET_RTX_COSTS
842 #define TARGET_RTX_COSTS msp430_rtx_costs
844 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED,
845 int code,
846 int outer_code ATTRIBUTE_UNUSED,
847 int opno ATTRIBUTE_UNUSED,
848 int * total,
849 bool speed ATTRIBUTE_UNUSED)
851 switch (code)
853 case SIGN_EXTEND:
854 if (GET_MODE (x) == SImode && outer_code == SET)
856 *total = COSTS_N_INSNS (4);
857 return true;
859 break;
860 case ASHIFT:
861 case ASHIFTRT:
862 case LSHIFTRT:
863 if (!msp430x)
865 *total = COSTS_N_INSNS (100);
866 return true;
868 break;
870 return false;
873 /* Function Entry and Exit */
875 /* The MSP430 call frame looks like this:
877 <higher addresses>
878 +--------------------+
880 | Stack Arguments |
882 +--------------------+ <-- "arg pointer"
884 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
886 +--------------------+
887 | SR if this func has|
888 | been called via an |
889 | interrupt. |
890 +--------------------+ <-- SP before prologue, also AP
892 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
894 +--------------------+ <-- "frame pointer"
896 | Locals |
898 +--------------------+
900 | Outgoing Args |
902 +--------------------+ <-- SP during function
903 <lower addresses>
907 /* We use this to wrap all emitted insns in the prologue, so they get
908 the "frame-related" (/f) flag set. */
909 static rtx
910 F (rtx x)
912 RTX_FRAME_RELATED_P (x) = 1;
913 return x;
916 /* This is the one spot that decides if a register is to be saved and
917 restored in the prologue/epilogue. */
918 static bool
919 msp430_preserve_reg_p (int regno)
921 /* PC, SP, SR, and the constant generator. */
922 if (regno <= 3)
923 return false;
925 /* FIXME: add interrupt, EH, etc. */
926 if (crtl->calls_eh_return)
927 return true;
929 /* Shouldn't be more than the above, but just in case... */
930 if (fixed_regs [regno])
931 return false;
933 /* Interrupt handlers save all registers they use, even
934 ones which are call saved. If they call other functions
935 then *every* register is saved. */
936 if (msp430_is_interrupt_func ())
937 return ! crtl->is_leaf || df_regs_ever_live_p (regno);
939 if (!call_used_regs [regno]
940 && df_regs_ever_live_p (regno))
941 return true;
943 return false;
946 /* Compute all the frame-related fields in our machine_function
947 structure. */
948 static void
949 msp430_compute_frame_info (void)
951 int i;
953 cfun->machine->computed = 1;
954 cfun->machine->framesize_regs = 0;
955 cfun->machine->framesize_locals = get_frame_size ();
956 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
958 for (i = 0; i < ARG_POINTER_REGNUM; i ++)
959 if (msp430_preserve_reg_p (i))
961 cfun->machine->need_to_save [i] = 1;
962 cfun->machine->framesize_regs += (TARGET_LARGE ? 4 : 2);
964 else
965 cfun->machine->need_to_save [i] = 0;
967 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
968 cfun->machine->framesize_locals ++;
970 cfun->machine->framesize = (cfun->machine->framesize_regs
971 + cfun->machine->framesize_locals
972 + cfun->machine->framesize_outgoing);
975 static inline bool
976 is_attr_func (const char * attr)
978 return lookup_attribute (attr, DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE;
981 /* Returns true if the current function has the "interrupt" attribute. */
983 bool
984 msp430_is_interrupt_func (void)
986 if (current_function_decl == NULL)
987 return false;
988 return is_attr_func ("interrupt");
991 static bool
992 is_wakeup_func (void)
994 return msp430_is_interrupt_func () && is_attr_func ("wakeup");
997 static inline bool
998 is_naked_func (void)
1000 return is_attr_func ("naked");
1003 static inline bool
1004 is_reentrant_func (void)
1006 return is_attr_func ("reentrant");
1009 static inline bool
1010 is_critical_func (void)
1012 return is_attr_func ("critical");
1015 #undef TARGET_ASM_FUNCTION_PROLOGUE
1016 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
1018 static void
1019 msp430_start_function (FILE *outfile, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
1021 int r, n;
1023 fprintf (outfile, "; start of function\n");
1025 if (DECL_ATTRIBUTES (current_function_decl) != NULL_TREE)
1027 fprintf (outfile, "; attributes: ");
1028 if (is_naked_func ())
1029 fprintf (outfile, "naked ");
1030 if (msp430_is_interrupt_func ())
1031 fprintf (outfile, "interrupt ");
1032 if (is_reentrant_func ())
1033 fprintf (outfile, "reentrant ");
1034 if (is_critical_func ())
1035 fprintf (outfile, "critical ");
1036 if (is_wakeup_func ())
1037 fprintf (outfile, "wakeup ");
1038 fprintf (outfile, "\n");
1041 fprintf (outfile, "; framesize_regs: %d\n", cfun->machine->framesize_regs);
1042 fprintf (outfile, "; framesize_locals: %d\n", cfun->machine->framesize_locals);
1043 fprintf (outfile, "; framesize_outgoing: %d\n", cfun->machine->framesize_outgoing);
1044 fprintf (outfile, "; framesize: %d\n", cfun->machine->framesize);
1045 fprintf (outfile, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM));
1046 fprintf (outfile, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM));
1048 n = 0;
1049 fprintf (outfile, "; saved regs:");
1050 for (r = 0; r < ARG_POINTER_REGNUM; r++)
1051 if (cfun->machine->need_to_save [r])
1053 fprintf (outfile, " %s", reg_names [r]);
1054 n = 1;
1056 if (n == 0)
1057 fprintf (outfile, "(none)");
1058 fprintf (outfile, "\n");
1061 /* Common code to change the stack pointer. */
1062 static void
1063 increment_stack (HOST_WIDE_INT amount)
1065 rtx inc;
1066 rtx sp = stack_pointer_rtx;
1068 if (amount == 0)
1069 return;
1071 if (amount < 0)
1073 inc = GEN_INT (- amount);
1074 if (TARGET_LARGE)
1075 F (emit_insn (gen_subpsi3 (sp, sp, inc)));
1076 else
1077 F (emit_insn (gen_subhi3 (sp, sp, inc)));
1079 else
1081 inc = GEN_INT (amount);
1082 if (TARGET_LARGE)
1083 emit_insn (gen_addpsi3 (sp, sp, inc));
1084 else
1085 emit_insn (gen_addhi3 (sp, sp, inc));
1089 /* Verify MSP430 specific attributes. */
1091 static tree
1092 msp430_attr (tree * node,
1093 tree name,
1094 tree args,
1095 int flags ATTRIBUTE_UNUSED,
1096 bool * no_add_attrs)
1098 gcc_assert (DECL_P (* node));
1100 if (args != NULL)
1102 tree value = TREE_VALUE (args);
1104 switch (TREE_CODE (value))
1106 case STRING_CST:
1107 if ( strcmp (TREE_STRING_POINTER (value), "reset")
1108 && strcmp (TREE_STRING_POINTER (value), "nmi")
1109 && strcmp (TREE_STRING_POINTER (value), "watchdog"))
1110 /* Allow the attribute to be added - the linker script
1111 being used may still recognise this name. */
1112 warning (OPT_Wattributes,
1113 "unrecognised interrupt vector argument of %qE attribute",
1114 name);
1115 break;
1117 case INTEGER_CST:
1118 if (TREE_INT_CST_LOW (value) > 63)
1119 /* Allow the attribute to be added - the linker script
1120 being used may still recognise this value. */
1121 warning (OPT_Wattributes,
1122 "numeric argument of %qE attribute must be in range 0..63",
1123 name);
1124 break;
1126 default:
1127 warning (OPT_Wattributes,
1128 "argument of %qE attribute is not a string constant or number",
1129 name);
1130 *no_add_attrs = true;
1131 break;
1135 if (TREE_CODE (* node) != FUNCTION_DECL)
1137 warning (OPT_Wattributes,
1138 "%qE attribute only applies to functions",
1139 name);
1140 * no_add_attrs = true;
1143 /* FIXME: We ought to check that the interrupt handler
1144 attribute has been applied to a void function. */
1145 /* FIXME: We should check that reentrant and critical
1146 functions are not naked and that critical functions
1147 are not reentrant. */
1149 return NULL_TREE;
1152 #undef TARGET_ATTRIBUTE_TABLE
1153 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
1155 /* Table of MSP430-specific attributes. */
1156 const struct attribute_spec msp430_attribute_table[] =
1158 /* Name min_len decl_req, fn_type_req, affects_type_identity
1159 max_len, type_req, handler. */
1160 { "interrupt", 0, 1, true, false, false, msp430_attr, false },
1161 { "naked", 0, 0, true, false, false, msp430_attr, false },
1162 { "reentrant", 0, 0, true, false, false, msp430_attr, false },
1163 { "critical", 0, 0, true, false, false, msp430_attr, false },
1164 { "wakeup", 0, 0, true, false, false, msp430_attr, false },
1165 { NULL, 0, 0, false, false, false, NULL, false }
1168 void
1169 msp430_start_function (FILE *file, const char *name, tree decl)
1171 tree int_attr;
1173 int_attr = lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl));
1174 if (int_attr != NULL_TREE)
1176 tree intr_vector = TREE_VALUE (int_attr);
1178 if (intr_vector != NULL_TREE)
1180 char buf[101];
1182 intr_vector = TREE_VALUE (intr_vector);
1184 /* The interrupt attribute has a vector value. Turn this into a
1185 section name, switch to that section and put the address of
1186 the current function into that vector slot. Note msp430_attr()
1187 has already verified the vector name for us. */
1188 if (TREE_CODE (intr_vector) == STRING_CST)
1189 sprintf (buf, "__interrupt_vector_%.80s",
1190 TREE_STRING_POINTER (intr_vector));
1191 else /* TREE_CODE (intr_vector) == INTEGER_CST */
1192 sprintf (buf, "__interrupt_vector_%u",
1193 (unsigned int) TREE_INT_CST_LOW (intr_vector));
1195 switch_to_section (get_section (buf, SECTION_CODE, decl));
1196 fputs ("\t.word\t", file);
1197 assemble_name (file, name);
1198 fputc ('\n', file);
1199 fputc ('\t', file);
1203 switch_to_section (function_section (decl));
1204 ASM_OUTPUT_FUNCTION_LABEL (file, name, decl);
1207 static section *
1208 msp430_function_section (tree decl, enum node_frequency freq, bool startup, bool exit)
1210 /* In large mode we must make sure that interrupt handlers are put into
1211 low memory as the vector table only accepts 16-bit addresses. */
1212 if (TARGET_LARGE
1213 && lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl)))
1214 return get_section (".lowtext", SECTION_CODE | SECTION_WRITE , decl);
1216 /* Otherwise, use the default function section. */
1217 return default_function_section (decl, freq, startup, exit);
1220 #undef TARGET_ASM_FUNCTION_SECTION
1221 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
1223 enum msp430_builtin
1225 MSP430_BUILTIN_BIC_SR,
1226 MSP430_BUILTIN_BIS_SR,
1227 MSP430_BUILTIN_max
1230 static GTY(()) tree msp430_builtins [(int) MSP430_BUILTIN_max];
1232 static void
1233 msp430_init_builtins (void)
1235 tree void_ftype_int = build_function_type_list (void_type_node, integer_type_node, NULL);
1237 msp430_builtins[MSP430_BUILTIN_BIC_SR] =
1238 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int,
1239 MSP430_BUILTIN_BIC_SR, BUILT_IN_MD, NULL, NULL_TREE);
1241 msp430_builtins[MSP430_BUILTIN_BIS_SR] =
1242 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int,
1243 MSP430_BUILTIN_BIS_SR, BUILT_IN_MD, NULL, NULL_TREE);
1246 static tree
1247 msp430_builtin_decl (unsigned code, bool initialize ATTRIBUTE_UNUSED)
1249 switch (code)
1251 case MSP430_BUILTIN_BIC_SR:
1252 case MSP430_BUILTIN_BIS_SR:
1253 return msp430_builtins[code];
1254 default:
1255 return error_mark_node;
1259 static rtx
1260 msp430_expand_builtin (tree exp,
1261 rtx target ATTRIBUTE_UNUSED,
1262 rtx subtarget ATTRIBUTE_UNUSED,
1263 enum machine_mode mode ATTRIBUTE_UNUSED,
1264 int ignore ATTRIBUTE_UNUSED)
1266 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
1267 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
1268 rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
1270 if (! msp430_is_interrupt_func ())
1272 error ("MSP430 builtin functions only work inside interrupt handlers");
1273 return NULL_RTX;
1276 if (! REG_P (arg1) && ! CONSTANT_P (arg1))
1277 arg1 = force_reg (mode, arg1);
1279 switch (fcode)
1281 case MSP430_BUILTIN_BIC_SR: emit_insn (gen_bic_SR (arg1)); break;
1282 case MSP430_BUILTIN_BIS_SR: emit_insn (gen_bis_SR (arg1)); break;
1283 default:
1284 internal_error ("bad builtin code");
1285 break;
1287 return NULL_RTX;
1290 #undef TARGET_INIT_BUILTINS
1291 #define TARGET_INIT_BUILTINS msp430_init_builtins
1293 #undef TARGET_EXPAND_BUILTIN
1294 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
1296 #undef TARGET_BUILTIN_DECL
1297 #define TARGET_BUILTIN_DECL msp430_builtin_decl
1299 void
1300 msp430_expand_prologue (void)
1302 int i, j;
1303 int fs;
1304 /* Always use stack_pointer_rtx instead of calling
1305 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
1306 that there is a single rtx representing the stack pointer,
1307 namely stack_pointer_rtx, and uses == to recognize it. */
1308 rtx sp = stack_pointer_rtx;
1309 rtx p;
1311 if (is_naked_func ())
1312 return;
1314 emit_insn (gen_prologue_start_marker ());
1316 if (is_critical_func ())
1318 emit_insn (gen_push_intr_state ());
1319 emit_insn (gen_disable_interrupts ());
1321 else if (is_reentrant_func ())
1322 emit_insn (gen_disable_interrupts ());
1324 if (!cfun->machine->computed)
1325 msp430_compute_frame_info ();
1327 if (flag_stack_usage_info)
1328 current_function_static_stack_size = cfun->machine->framesize;
1330 if (crtl->args.pretend_args_size)
1332 rtx note;
1334 gcc_assert (crtl->args.pretend_args_size == 2);
1336 p = emit_insn (gen_grow_and_swap ());
1338 /* Document the stack decrement... */
1339 note = F (gen_rtx_SET (Pmode, stack_pointer_rtx,
1340 gen_rtx_MINUS (Pmode, stack_pointer_rtx, GEN_INT (2))));
1341 add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
1343 /* ...and the establishment of a new location for the return address. */
1344 note = F (gen_rtx_SET (Pmode, gen_rtx_MEM (Pmode,
1345 gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-2))),
1346 pc_rtx));
1347 add_reg_note (p, REG_CFA_OFFSET, note);
1348 F (p);
1351 for (i = 15; i >= 4; i--)
1352 if (cfun->machine->need_to_save [i])
1354 int seq, count;
1355 rtx note;
1357 for (seq = i - 1; seq >= 4 && cfun->machine->need_to_save[seq]; seq --)
1359 count = i - seq;
1361 if (msp430x)
1363 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
1364 p = F (emit_insn (gen_pushm (gen_rtx_REG (Pmode, i),
1365 GEN_INT (count))));
1367 note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1));
1369 XVECEXP (note, 0, 0)
1370 = F (gen_rtx_SET (VOIDmode,
1371 stack_pointer_rtx,
1372 gen_rtx_PLUS (Pmode,
1373 stack_pointer_rtx,
1374 GEN_INT (count * (TARGET_LARGE ? -4 : -2)))));
1376 /* *sp-- = R[i-j] */
1377 /* sp+N R10
1379 sp R4 */
1380 for (j = 0; j < count; j ++)
1382 rtx addr;
1383 int ofs = (count - j - 1) * (TARGET_LARGE ? 4 : 2);
1385 if (ofs)
1386 addr = gen_rtx_PLUS (Pmode, sp, GEN_INT (ofs));
1387 else
1388 addr = stack_pointer_rtx;
1390 XVECEXP (note, 0, j + 1) =
1391 F (gen_rtx_SET (VOIDmode,
1392 gen_rtx_MEM (Pmode, addr),
1393 gen_rtx_REG (Pmode, i - j)) );
1396 add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
1397 i -= count - 1;
1399 else
1400 F (emit_insn (gen_push (gen_rtx_REG (Pmode, i))));
1403 if (frame_pointer_needed)
1404 F (emit_move_insn (gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM), sp));
1406 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1408 increment_stack (- fs);
1410 emit_insn (gen_prologue_end_marker ());
1413 void
1414 msp430_expand_epilogue (int is_eh)
1416 int i;
1417 int fs;
1418 int helper_n = 0;
1420 if (is_naked_func ())
1421 return;
1423 if (cfun->machine->need_to_save [10])
1425 /* Check for a helper function. */
1426 helper_n = 7; /* For when the loop below never sees a match. */
1427 for (i = 9; i >= 4; i--)
1428 if (!cfun->machine->need_to_save [i])
1430 helper_n = 10 - i;
1431 for (; i >= 4; i--)
1432 if (cfun->machine->need_to_save [i])
1434 helper_n = 0;
1435 break;
1437 break;
1441 emit_insn (gen_epilogue_start_marker ());
1443 if (cfun->decl && strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun->decl)), "main") == 0)
1444 emit_insn (gen_msp430_refsym_need_exit ());
1446 if (is_wakeup_func ())
1447 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
1448 status register current residing on the stack. When this function
1449 executes its RETI instruction the SR will be updated with this saved
1450 value, thus ensuring that the processor is woken up from any low power
1451 state in which it may be residing. */
1452 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
1454 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1456 increment_stack (fs);
1458 if (is_eh)
1460 /* We need to add the right "SP" register save just after the
1461 regular ones, so that when we pop it off we're in the EH
1462 return frame, not this one. This overwrites our own return
1463 address, but we're not going to be returning anyway. */
1464 rtx r12 = gen_rtx_REG (Pmode, 12);
1465 rtx (*addPmode)(rtx, rtx, rtx) = TARGET_LARGE ? gen_addpsi3 : gen_addhi3;
1467 /* R12 will hold the new SP. */
1468 i = cfun->machine->framesize_regs;
1469 emit_move_insn (r12, stack_pointer_rtx);
1470 emit_insn (addPmode (r12, r12, EH_RETURN_STACKADJ_RTX));
1471 emit_insn (addPmode (r12, r12, GEN_INT (i)));
1472 emit_move_insn (gen_rtx_MEM (Pmode, plus_constant (Pmode, stack_pointer_rtx, i)), r12);
1475 for (i = 4; i <= 15; i++)
1476 if (cfun->machine->need_to_save [i])
1478 int seq, count;
1480 for (seq = i + 1; seq <= 15 && cfun->machine->need_to_save[seq]; seq ++)
1482 count = seq - i;
1484 if (msp430x)
1486 /* Note: With TARGET_LARGE we still use
1487 POPM as POPX.A is two bytes bigger. */
1488 emit_insn (gen_popm (stack_pointer_rtx, GEN_INT (seq - 1),
1489 GEN_INT (count)));
1490 i += count - 1;
1492 else if (i == 11 - helper_n
1493 && ! msp430_is_interrupt_func ()
1494 && ! is_reentrant_func ()
1495 && ! is_critical_func ()
1496 && crtl->args.pretend_args_size == 0
1497 /* Calling the helper takes as many bytes as the POP;RET sequence. */
1498 && helper_n > 1
1499 && !is_eh)
1501 emit_insn (gen_epilogue_helper (GEN_INT (helper_n)));
1502 return;
1504 else
1505 emit_insn (gen_pop (gen_rtx_REG (Pmode, i)));
1508 if (is_eh)
1510 /* Also pop SP, which puts us into the EH return frame. Except
1511 that you can't "pop" sp, you have to just load it off the
1512 stack. */
1513 emit_move_insn (stack_pointer_rtx, gen_rtx_MEM (Pmode, stack_pointer_rtx));
1516 if (crtl->args.pretend_args_size)
1517 emit_insn (gen_swap_and_shrink ());
1519 if (is_critical_func ())
1520 emit_insn (gen_pop_intr_state ());
1521 else if (is_reentrant_func ())
1522 emit_insn (gen_enable_interrupts ());
1524 emit_jump_insn (gen_msp_return ());
1527 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
1528 m32c_emit_eh_epilogue. */
1530 msp430_eh_return_stackadj_rtx (void)
1532 if (!cfun->machine->eh_stack_adjust)
1534 rtx sa;
1536 sa = gen_rtx_REG (Pmode, 15);
1537 cfun->machine->eh_stack_adjust = sa;
1539 return cfun->machine->eh_stack_adjust;
1542 /* This function is called before reload, to "fix" the stack in
1543 preparation for an EH return. */
1544 void
1545 msp430_expand_eh_return (rtx eh_handler)
1547 /* These are all Pmode */
1548 rtx ap, sa, ra, tmp;
1550 ap = arg_pointer_rtx;
1551 sa = msp430_eh_return_stackadj_rtx ();
1552 ra = eh_handler;
1554 tmp = ap;
1555 tmp = gen_rtx_PLUS (Pmode, ap, sa);
1556 tmp = plus_constant (Pmode, tmp, TARGET_LARGE ? -4 : -2);
1557 tmp = gen_rtx_MEM (Pmode, tmp);
1558 emit_move_insn (tmp, ra);
1561 /* This is a list of MD patterns that implement fixed-count shifts. */
1562 static struct
1564 const char *name;
1565 int count;
1566 int need_430x;
1567 rtx (*genfunc)(rtx,rtx);
1569 const_shift_helpers[] =
1571 #define CSH(N,C,X,G) { "__mspabi_"N, C, X, gen_##G }
1573 CSH ("slli", 1, 1, slli_1),
1574 CSH ("slll", 1, 1, slll_1),
1575 CSH ("slll", 2, 1, slll_2),
1577 CSH ("srai", 1, 0, srai_1),
1578 CSH ("sral", 1, 0, sral_1),
1579 CSH ("sral", 2, 0, sral_2),
1581 CSH ("srll", 1, 0, srll_1),
1582 CSH ("srll", 2, 1, srll_2x),
1583 { 0, 0, 0, 0 }
1584 #undef CSH
1587 /* The MSP430 ABI defines a number of helper functions that should be
1588 used for, for example, 32-bit shifts. This function is called to
1589 emit such a function, using the table above to optimize some
1590 cases. */
1591 void
1592 msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variants)
1594 rtx c, f;
1595 char *helper_const = NULL;
1596 int arg2 = 13;
1597 int arg1sz = 1;
1598 enum machine_mode arg0mode = GET_MODE (operands[0]);
1599 enum machine_mode arg1mode = GET_MODE (operands[1]);
1600 enum machine_mode arg2mode = GET_MODE (operands[2]);
1601 int have_430x = msp430x ? 1 : 0;
1603 if (CONST_INT_P (operands[2]))
1605 int i;
1607 for (i=0; const_shift_helpers[i].name; i++)
1609 if (const_shift_helpers[i].need_430x <= have_430x
1610 && strcmp (helper_name, const_shift_helpers[i].name) == 0
1611 && INTVAL (operands[2]) == const_shift_helpers[i].count)
1613 emit_insn (const_shift_helpers[i].genfunc (operands[0], operands[1]));
1614 return;
1619 if (arg1mode == VOIDmode)
1620 arg1mode = arg0mode;
1621 if (arg2mode == VOIDmode)
1622 arg2mode = arg0mode;
1624 if (arg1mode == SImode)
1626 arg2 = 14;
1627 arg1sz = 2;
1630 if (const_variants
1631 && CONST_INT_P (operands[2])
1632 && INTVAL (operands[2]) >= 1
1633 && INTVAL (operands[2]) <= 15)
1635 /* Note that the INTVAL is limited in value and length by the conditional above. */
1636 int len = strlen (helper_name) + 4;
1637 helper_const = (char *) xmalloc (len);
1638 snprintf (helper_const, len, "%s_%d", helper_name, (int) INTVAL (operands[2]));
1641 emit_move_insn (gen_rtx_REG (arg1mode, 12),
1642 operands[1]);
1643 if (!helper_const)
1644 emit_move_insn (gen_rtx_REG (arg2mode, arg2),
1645 operands[2]);
1647 c = gen_call_value_internal (gen_rtx_REG (arg0mode, 12),
1648 gen_rtx_SYMBOL_REF (VOIDmode, helper_const ? helper_const : helper_name),
1649 GEN_INT (0));
1650 c = emit_call_insn (c);
1651 RTL_CONST_CALL_P (c) = 1;
1653 f = 0;
1654 use_regs (&f, 12, arg1sz);
1655 if (!helper_const)
1656 use_regs (&f, arg2, 1);
1657 add_function_usage_to (c, f);
1659 emit_move_insn (operands[0],
1660 gen_rtx_REG (arg0mode, 12));
1663 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
1664 void
1665 msp430_fixup_compare_operands (enum machine_mode my_mode, rtx * operands)
1667 /* constants we're looking for, not constants which are allowed. */
1668 int const_op_idx = 1;
1670 if (msp430_reversible_cmp_operator (operands[0], VOIDmode))
1671 const_op_idx = 2;
1673 if (GET_CODE (operands[const_op_idx]) != REG
1674 && GET_CODE (operands[const_op_idx]) != MEM)
1675 operands[const_op_idx] = copy_to_mode_reg (my_mode, operands[const_op_idx]);
1678 /* Simplify_gen_subreg() doesn't handle memory references the way we
1679 need it to below, so we use this function for when we must get a
1680 valid subreg in a "natural" state. */
1682 msp430_subreg (enum machine_mode mode, rtx r, enum machine_mode omode, int byte)
1684 rtx rv;
1686 if (GET_CODE (r) == SUBREG
1687 && SUBREG_BYTE (r) == 0)
1689 rtx ireg = SUBREG_REG (r);
1690 enum machine_mode imode = GET_MODE (ireg);
1692 /* special case for (HI (SI (PSI ...), 0)) */
1693 if (imode == PSImode
1694 && mode == HImode
1695 && byte == 0)
1696 rv = gen_rtx_SUBREG (mode, ireg, byte);
1697 else
1698 rv = simplify_gen_subreg (mode, ireg, imode, byte);
1700 else if (GET_CODE (r) == MEM)
1701 rv = adjust_address (r, mode, byte);
1702 else
1703 rv = simplify_gen_subreg (mode, r, omode, byte);
1705 if (!rv)
1706 gcc_unreachable ();
1708 return rv;
1711 /* Called by movsi_x to generate the HImode operands. */
1712 void
1713 msp430_split_movsi (rtx *operands)
1715 rtx op00, op02, op10, op12;
1717 op00 = msp430_subreg (HImode, operands[0], SImode, 0);
1718 op02 = msp430_subreg (HImode, operands[0], SImode, 2);
1720 if (GET_CODE (operands[1]) == CONST
1721 || GET_CODE (operands[1]) == SYMBOL_REF)
1723 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
1724 op10 = gen_rtx_CONST (HImode, op10);
1725 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
1726 op12 = gen_rtx_CONST (HImode, op12);
1728 else
1730 op10 = msp430_subreg (HImode, operands[1], SImode, 0);
1731 op12 = msp430_subreg (HImode, operands[1], SImode, 2);
1734 if (rtx_equal_p (operands[0], operands[1]))
1736 operands[2] = op02;
1737 operands[4] = op12;
1738 operands[3] = op00;
1739 operands[5] = op10;
1741 else if (rtx_equal_p (op00, op12)
1742 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
1743 || (REG_P (op00) && reg_mentioned_p (op00, op10))
1744 /* Or storing (rN) into mem (rN). */
1745 || (REG_P (op10) && reg_mentioned_p (op10, op00))
1748 operands[2] = op02;
1749 operands[4] = op12;
1750 operands[3] = op00;
1751 operands[5] = op10;
1753 else
1755 operands[2] = op00;
1756 operands[4] = op10;
1757 operands[3] = op02;
1758 operands[5] = op12;
1763 /* The MSPABI specifies the names of various helper functions, many of
1764 which are compatible with GCC's helpers. This table maps the GCC
1765 name to the MSPABI name. */
1766 static const struct
1768 char const * const gcc_name;
1769 char const * const ti_name;
1771 helper_function_name_mappings [] =
1773 /* Floating point to/from integer conversions. */
1774 { "__truncdfsf2", "__mspabi_cvtdf" },
1775 { "__extendsfdf2", "__mspabi_cvtfd" },
1776 { "__fixdfhi", "__mspabi_fixdi" },
1777 { "__fixdfsi", "__mspabi_fixdli" },
1778 { "__fixdfdi", "__mspabi_fixdlli" },
1779 { "__fixunsdfhi", "__mspabi_fixdu" },
1780 { "__fixunsdfsi", "__mspabi_fixdul" },
1781 { "__fixunsdfdi", "__mspabi_fixdull" },
1782 { "__fixsfhi", "__mspabi_fixfi" },
1783 { "__fixsfsi", "__mspabi_fixfli" },
1784 { "__fixsfdi", "__mspabi_fixflli" },
1785 { "__fixunsfhi", "__mspabi_fixfu" },
1786 { "__fixunsfsi", "__mspabi_fixful" },
1787 { "__fixunsfdi", "__mspabi_fixfull" },
1788 { "__floathisf", "__mspabi_fltif" },
1789 { "__floatsisf", "__mspabi_fltlif" },
1790 { "__floatdisf", "__mspabi_fltllif" },
1791 { "__floathidf", "__mspabi_fltid" },
1792 { "__floatsidf", "__mspabi_fltlid" },
1793 { "__floatdidf", "__mspabi_fltllid" },
1794 { "__floatunhisf", "__mspabi_fltuf" },
1795 { "__floatunsisf", "__mspabi_fltulf" },
1796 { "__floatundisf", "__mspabi_fltullf" },
1797 { "__floatunhidf", "__mspabi_fltud" },
1798 { "__floatunsidf", "__mspabi_fltuld" },
1799 { "__floatundidf", "__mspabi_fltulld" },
1801 /* Floating point comparisons. */
1802 /* GCC uses individual functions for each comparison, TI uses one
1803 compare <=> function. */
1805 /* Floating point arithmatic */
1806 { "__adddf3", "__mspabi_addd" },
1807 { "__addsf3", "__mspabi_addf" },
1808 { "__divdf3", "__mspabi_divd" },
1809 { "__divsf3", "__mspabi_divf" },
1810 { "__muldf3", "__mspabi_mpyd" },
1811 { "__mulsf3", "__mspabi_mpyf" },
1812 { "__subdf3", "__mspabi_subd" },
1813 { "__subsf3", "__mspabi_subf" },
1814 /* GCC does not use helper functions for negation */
1816 /* Integer multiply, divide, remainder. */
1817 { "__mulhi3", "__mspabi_mpyi" },
1818 { "__mulsi3", "__mspabi_mpyl" },
1819 { "__muldi3", "__mspabi_mpyll" },
1820 #if 0
1821 /* Clarify signed vs unsigned first. */
1822 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
1823 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
1824 #endif
1826 { "__divhi3", "__mspabi_divi" },
1827 { "__divsi3", "__mspabi_divli" },
1828 { "__divdi3", "__mspabi_divlli" },
1829 { "__udivhi3", "__mspabi_divu" },
1830 { "__udivsi3", "__mspabi_divlu" },
1831 { "__udivdi3", "__mspabi_divllu" },
1832 { "__modhi3", "__mspabi_remi" },
1833 { "__modsi3", "__mspabi_remli" },
1834 { "__moddi3", "__mspabi_remlli" },
1835 { "__umodhi3", "__mspabi_remu" },
1836 { "__umodsi3", "__mspabi_remul" },
1837 { "__umoddi3", "__mspabi_remull" },
1839 /* Bitwise operations. */
1840 /* Rotation - no rotation support yet. */
1841 /* Logical left shift - gcc already does these itself. */
1842 /* Arithmetic left shift - gcc already does these itself. */
1843 /* Arithmetic right shift - gcc already does these itself. */
1845 { NULL, NULL }
1848 /* Returns true if the current MCU is an F5xxx series. */
1849 bool
1850 msp430_is_f5_mcu (void)
1852 if (target_mcu == NULL)
1853 return false;
1854 return strncasecmp (target_mcu, "msp430f5", 8) == 0;
1857 /* Returns true id the current MCU has a second generation 32-bit hardware multiplier. */
1858 static bool
1859 has_32bit_hw_mult (void)
1861 static const char * known_32bit_mult_mcus [] =
1863 "msp430f4783", "msp430f4793", "msp430f4784",
1864 "msp430f4794", "msp430f47126", "msp430f47127",
1865 "msp430f47163", "msp430f47173", "msp430f47183",
1866 "msp430f47193", "msp430f47166", "msp430f47176",
1867 "msp430f47186", "msp430f47196", "msp430f47167",
1868 "msp430f47177", "msp430f47187", "msp430f47197"
1870 int i;
1871 if (target_mcu == NULL)
1872 return false;
1874 for (i = ARRAY_SIZE (known_32bit_mult_mcus); i--;)
1875 if (strcasecmp (target_mcu, known_32bit_mult_mcus[i]) == 0)
1876 return true;
1878 return false;
1881 /* Returns true if hardware multiply is supported by the chosen MCU. */
1882 bool
1883 msp430_hwmult_enabled (void)
1885 if (target_mcu == NULL)
1886 return false;
1888 if (!ENABLE_HWMULT)
1889 return false;
1891 if (msp430_is_interrupt_func ())
1892 return false;
1894 if (msp430_is_f5_mcu () || has_32bit_hw_mult ())
1895 return true;
1897 return false;
1900 /* This function does the same as the default, but it will replace GCC
1901 function names with the MSPABI-specified ones. */
1902 void
1903 msp430_output_labelref (FILE *file, const char *name)
1905 int i;
1907 for (i = 0; helper_function_name_mappings [i].gcc_name; i++)
1908 if (strcmp (helper_function_name_mappings [i].gcc_name, name) == 0)
1910 name = helper_function_name_mappings [i].ti_name;
1911 break;
1914 /* If we have been given a specific MCU name then we may be
1915 able to make use of its hardware multiply capabilities. */
1916 if (msp430_hwmult_enabled ())
1918 if (strcmp ("__mspabi_mpyi", name) == 0)
1920 if (msp430_is_f5_mcu ())
1921 name = "__mulhi2_f5";
1922 else
1923 name = "__mulhi2";
1925 else if (strcmp ("__mspabi_mpyl", name) == 0)
1927 if (msp430_is_f5_mcu ())
1928 name = "__mulsi2_f5";
1929 else if (has_32bit_hw_mult ())
1930 name = "__mulsi2_hw32";
1931 else
1932 name = "__mulsi2";
1936 fputs (name, file);
1939 /* Common code for msp430_print_operand... */
1941 static void
1942 msp430_print_operand_raw (FILE * file, rtx op)
1944 HOST_WIDE_INT i;
1946 switch (GET_CODE (op))
1948 case REG:
1949 fprintf (file, "%s", reg_names [REGNO (op)]);
1950 break;
1952 case CONST_INT:
1953 i = INTVAL (op);
1954 if (TARGET_ASM_HEX)
1955 fprintf (file, "%#" HOST_WIDE_INT_PRINT "x", i);
1956 else
1957 fprintf (file, "%" HOST_WIDE_INT_PRINT "d", i);
1958 break;
1960 case CONST:
1961 case PLUS:
1962 case MINUS:
1963 case SYMBOL_REF:
1964 case LABEL_REF:
1965 output_addr_const (file, op);
1966 break;
1968 default:
1969 print_rtl (file, op);
1970 break;
1974 #undef TARGET_PRINT_OPERAND_ADDRESS
1975 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
1977 /* Output to stdio stream FILE the assembler syntax for an
1978 instruction operand that is a memory reference whose address
1979 is ADDR. */
1981 static void
1982 msp430_print_operand_addr (FILE * file, rtx addr)
1984 switch (GET_CODE (addr))
1986 case PLUS:
1987 msp430_print_operand_raw (file, XEXP (addr, 1));
1988 gcc_assert (REG_P (XEXP (addr, 0)));
1989 fprintf (file, "(%s)", reg_names [REGNO (XEXP (addr, 0))]);
1990 return;
1992 case REG:
1993 fprintf (file, "@");
1994 break;
1996 case CONST:
1997 case CONST_INT:
1998 case SYMBOL_REF:
1999 case LABEL_REF:
2000 fprintf (file, "&");
2001 break;
2003 default:
2004 break;
2007 msp430_print_operand_raw (file, addr);
2010 #undef TARGET_PRINT_OPERAND
2011 #define TARGET_PRINT_OPERAND msp430_print_operand
2013 /* A low 16-bits of int/lower of register pair
2014 B high 16-bits of int/higher of register pair
2015 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
2016 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
2017 H like %B (for backwards compatibility)
2018 I inverse of value
2019 J an integer without a # prefix
2020 L like %A (for backwards compatibility)
2021 O offset of the top of the stack
2022 Q like X but generates an A postfix
2023 R inverse of condition code, unsigned.
2024 X X instruction postfix in large mode
2025 Y value - 4
2026 Z value - 1
2027 b .B or .W or .A, depending upon the mode
2028 p bit position
2029 r inverse of condition code
2030 x like X but only for pointers. */
2032 static void
2033 msp430_print_operand (FILE * file, rtx op, int letter)
2035 rtx addr;
2037 /* We can't use c, n, a, or l. */
2038 switch (letter)
2040 case 'Z':
2041 gcc_assert (CONST_INT_P (op));
2042 /* Print the constant value, less one. */
2043 fprintf (file, "#%ld", INTVAL (op) - 1);
2044 return;
2045 case 'Y':
2046 gcc_assert (CONST_INT_P (op));
2047 /* Print the constant value, less four. */
2048 fprintf (file, "#%ld", INTVAL (op) - 4);
2049 return;
2050 case 'I':
2051 if (GET_CODE (op) == CONST_INT)
2053 /* Inverse of constants */
2054 int i = INTVAL (op);
2055 fprintf (file, "%d", ~i);
2056 return;
2058 op = XEXP (op, 0);
2059 break;
2060 case 'r': /* Conditional jump where the condition is reversed. */
2061 switch (GET_CODE (op))
2063 case EQ: fprintf (file, "NE"); break;
2064 case NE: fprintf (file, "EQ"); break;
2065 case GEU: fprintf (file, "LO"); break;
2066 case LTU: fprintf (file, "HS"); break;
2067 case GE: fprintf (file, "L"); break;
2068 case LT: fprintf (file, "GE"); break;
2069 /* Assume these have reversed operands. */
2070 case GTU: fprintf (file, "HS"); break;
2071 case LEU: fprintf (file, "LO"); break;
2072 case GT: fprintf (file, "GE"); break;
2073 case LE: fprintf (file, "L"); break;
2074 default:
2075 msp430_print_operand_raw (file, op);
2076 break;
2078 return;
2079 case 'R': /* Conditional jump where the operands are reversed. */
2080 switch (GET_CODE (op))
2082 case GTU: fprintf (file, "LO"); break;
2083 case LEU: fprintf (file, "HS"); break;
2084 case GT: fprintf (file, "L"); break;
2085 case LE: fprintf (file, "GE"); break;
2086 default:
2087 msp430_print_operand_raw (file, op);
2088 break;
2090 return;
2091 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
2092 gcc_assert (CONST_INT_P (op));
2093 fprintf (file, "#%d", 1 << INTVAL (op));
2094 return;
2095 case 'b':
2096 switch (GET_MODE (op))
2098 case QImode: fprintf (file, ".B"); return;
2099 case HImode: fprintf (file, ".W"); return;
2100 case PSImode: fprintf (file, ".A"); return;
2101 case SImode: fprintf (file, ".A"); return;
2102 default:
2103 return;
2105 case 'A':
2106 case 'L': /* Low half. */
2107 switch (GET_CODE (op))
2109 case MEM:
2110 op = adjust_address (op, Pmode, 0);
2111 break;
2112 case REG:
2113 break;
2114 case CONST_INT:
2115 op = GEN_INT (INTVAL (op) & 0xffff);
2116 letter = 0;
2117 break;
2118 default:
2119 /* If you get here, figure out a test case :-) */
2120 gcc_unreachable ();
2122 break;
2123 case 'B':
2124 case 'H': /* high half */
2125 switch (GET_CODE (op))
2127 case MEM:
2128 op = adjust_address (op, Pmode, 2);
2129 break;
2130 case REG:
2131 op = gen_rtx_REG (Pmode, REGNO (op) + 1);
2132 break;
2133 case CONST_INT:
2134 op = GEN_INT (INTVAL (op) >> 16);
2135 letter = 0;
2136 break;
2137 default:
2138 /* If you get here, figure out a test case :-) */
2139 gcc_unreachable ();
2141 break;
2142 case 'C':
2143 switch (GET_CODE (op))
2145 case MEM:
2146 op = adjust_address (op, Pmode, 3);
2147 break;
2148 case REG:
2149 op = gen_rtx_REG (Pmode, REGNO (op) + 2);
2150 break;
2151 case CONST_INT:
2152 op = GEN_INT ((long long) INTVAL (op) >> 32);
2153 letter = 0;
2154 break;
2155 default:
2156 /* If you get here, figure out a test case :-) */
2157 gcc_unreachable ();
2159 break;
2160 case 'D':
2161 switch (GET_CODE (op))
2163 case MEM:
2164 op = adjust_address (op, Pmode, 4);
2165 break;
2166 case REG:
2167 op = gen_rtx_REG (Pmode, REGNO (op) + 3);
2168 break;
2169 case CONST_INT:
2170 op = GEN_INT ((long long) INTVAL (op) >> 48);
2171 letter = 0;
2172 break;
2173 default:
2174 /* If you get here, figure out a test case :-) */
2175 gcc_unreachable ();
2177 break;
2179 case 'X':
2180 /* This is used to turn, for example, an ADD opcode into an ADDX
2181 opcode when we're using 20-bit addresses. */
2182 if (TARGET_LARGE)
2183 fprintf (file, "X");
2184 /* We don't care which operand we use, but we want 'X' in the MD
2185 file, so we do it this way. */
2186 return;
2188 case 'x':
2189 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
2190 if (TARGET_LARGE && GET_MODE (op) == PSImode)
2191 fprintf (file, "X");
2192 return;
2194 case 'Q':
2195 /* Likewise, for BR -> BRA. */
2196 if (TARGET_LARGE)
2197 fprintf (file, "A");
2198 return;
2200 case 'O':
2201 /* Computes the offset to the top of the stack for the current frame.
2202 This has to be done here rather than in, say, msp430_expand_builtin()
2203 because builtins are expanded before the frame layout is determined. */
2204 fprintf (file, "%d",
2205 msp430_initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM)
2206 - 2);
2207 return;
2209 case 'J':
2210 gcc_assert (GET_CODE (op) == CONST_INT);
2211 case 0:
2212 break;
2213 default:
2214 output_operand_lossage ("invalid operand prefix");
2215 return;
2218 switch (GET_CODE (op))
2220 case REG:
2221 msp430_print_operand_raw (file, op);
2222 break;
2224 case MEM:
2225 addr = XEXP (op, 0);
2226 msp430_print_operand_addr (file, addr);
2227 break;
2229 case CONST_INT:
2230 case CONST:
2231 case SYMBOL_REF:
2232 case LABEL_REF:
2233 if (letter == 0)
2234 fprintf (file, "#");
2235 msp430_print_operand_raw (file, op);
2236 break;
2238 case EQ: fprintf (file, "EQ"); break;
2239 case NE: fprintf (file, "NE"); break;
2240 case GEU: fprintf (file, "HS"); break;
2241 case LTU: fprintf (file, "LO"); break;
2242 case GE: fprintf (file, "GE"); break;
2243 case LT: fprintf (file, "L"); break;
2245 default:
2246 print_rtl (file, op);
2247 break;
2252 /* Frame stuff. */
2255 msp430_return_addr_rtx (int count)
2257 int ra_size;
2258 if (count)
2259 return NULL_RTX;
2261 ra_size = TARGET_LARGE ? 4 : 2;
2262 if (crtl->args.pretend_args_size)
2263 ra_size += 2;
2265 return gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, arg_pointer_rtx, GEN_INT (- ra_size)));
2269 msp430_incoming_return_addr_rtx (void)
2271 return gen_rtx_MEM (Pmode, stack_pointer_rtx);
2274 /* Instruction generation stuff. */
2276 /* Generate a sequence of instructions to sign-extend an HI
2277 value into an SI value. Handles the tricky case where
2278 we are overwriting the destination. */
2280 const char *
2281 msp430x_extendhisi (rtx * operands)
2283 if (REGNO (operands[0]) == REGNO (operands[1]))
2284 /* Low word of dest == source word. */
2285 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
2287 if (! msp430x)
2288 /* Note: This sequence is approximately the same length as invoking a helper
2289 function to perform the sign-extension, as in:
2291 MOV.W %1, %L0
2292 MOV.W %1, r12
2293 CALL __mspabi_srai_15
2294 MOV.W r12, %H0
2296 but this version does not involve any function calls or using argument
2297 registers, so it reduces register pressure. */
2298 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
2300 if (REGNO (operands[0]) + 1 == REGNO (operands[1]))
2301 /* High word of dest == source word. */
2302 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
2304 /* No overlap between dest and source. */
2305 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
2308 /* Likewise for logical right shifts. */
2309 const char *
2310 msp430x_logical_shift_right (rtx amount)
2312 /* The MSP430X's logical right shift instruction - RRUM - does
2313 not use an extension word, so we cannot encode a repeat count.
2314 Try various alternatives to work around this. If the count
2315 is in a register we are stuck, hence the assert. */
2316 gcc_assert (CONST_INT_P (amount));
2318 if (INTVAL (amount) <= 0
2319 || INTVAL (amount) >= 16)
2320 return "# nop logical shift.";
2322 if (INTVAL (amount) > 0
2323 && INTVAL (amount) < 5)
2324 return "rrum.w\t%2, %0"; /* Two bytes. */
2326 if (INTVAL (amount) > 4
2327 && INTVAL (amount) < 9)
2328 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
2330 /* First we logically shift right by one. Now we know
2331 that the top bit is zero and we can use the arithmetic
2332 right shift instruction to perform the rest of the shift. */
2333 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
2336 struct gcc_target targetm = TARGET_INITIALIZER;
2338 #include "gt-msp430.h"