* config/msp430/msp430.h (LIB_SPEC): Add -lcrt
[official-gcc.git] / gcc / config / msp430 / msp430.c
blob97fa3f5a18b69890e9080aa9fc2bc75cfd0f0a5a
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"
57 static void msp430_compute_frame_info (void);
61 /* Run-time Target Specification */
63 bool msp430x = false;
65 struct GTY(()) machine_function
67 /* If set, the rest of the fields have been computed. */
68 int computed;
69 /* Which registers need to be saved in the pro/epilogue. */
70 int need_to_save [FIRST_PSEUDO_REGISTER];
72 /* These fields describe the frame layout... */
73 /* arg pointer */
74 /* 2/4 bytes for saved PC */
75 int framesize_regs;
76 /* frame pointer */
77 int framesize_locals;
78 int framesize_outgoing;
79 /* stack pointer */
80 int framesize;
82 /* How much we adjust the stack when returning from an exception
83 handler. */
84 rtx eh_stack_adjust;
87 /* This is our init_machine_status, as set in
88 msp_option_override. */
89 static struct machine_function *
90 msp430_init_machine_status (void)
92 struct machine_function *m;
94 m = ggc_alloc_cleared_machine_function ();
96 return m;
99 #undef TARGET_HANDLE_OPTION
100 #define TARGET_HANDLE_OPTION msp430_handle_option
102 bool
103 msp430_handle_option (struct gcc_options *opts ATTRIBUTE_UNUSED,
104 struct gcc_options *opts_set ATTRIBUTE_UNUSED,
105 const struct cl_decoded_option *decoded ATTRIBUTE_UNUSED,
106 location_t loc ATTRIBUTE_UNUSED)
108 return true;
111 #undef TARGET_OPTION_OVERRIDE
112 #define TARGET_OPTION_OVERRIDE msp430_option_override
114 /* This list provides a set of known MCU names that support the MSP430X
115 ISA. The list has been provided by TI and should be kept in sync with
116 the ones in:
118 gcc/config/msp430/t-msp430
119 gas/config/tc-msp430.c
121 FIXME: We ought to read the names in from a file at run, rather
122 than having them built in like this. Also such a file should be
123 shared with gas. */
125 static const char * msp430x_names [] =
127 "cc430f5123", "cc430f5125", "cc430f5133", "cc430f5135", "cc430f5137",
128 "cc430f5143", "cc430f5145", "cc430f5147", "cc430f6125", "cc430f6126",
129 "cc430f6127", "cc430f6135", "cc430f6137", "cc430f6143", "cc430f6145",
130 "cc430f6147", "msp430bt5190", "msp430cg4616", "msp430cg4617", "msp430cg4618",
131 "msp430cg4619", "msp430f2416", "msp430f2417", "msp430f2418", "msp430f2419",
132 "msp430f2616", "msp430f2617", "msp430f2618", "msp430f2619", "msp430f4616",
133 "msp430f46161", "msp430f4617", "msp430f46171", "msp430f4618", "msp430f46181",
134 "msp430f4619", "msp430f46191", "msp430f47126", "msp430f47127", "msp430f47163",
135 "msp430f47166", "msp430f47167", "msp430f47173", "msp430f47176", "msp430f47177",
136 "msp430f47183", "msp430f47186", "msp430f47187", "msp430f47193", "msp430f47196",
137 "msp430f47197", "msp430f5131", "msp430f5132", "msp430f5151", "msp430f5152",
138 "msp430f5171", "msp430f5172", "msp430f5212", "msp430f5213", "msp430f5214",
139 "msp430f5217", "msp430f5218", "msp430f5219", "msp430f5222", "msp430f5223",
140 "msp430f5224", "msp430f5227", "msp430f5228", "msp430f5229", "msp430f5304",
141 "msp430f5308", "msp430f5309", "msp430f5310", "msp430f5324", "msp430f5325",
142 "msp430f5326", "msp430f5327", "msp430f5328", "msp430f5329", "msp430f5333",
143 "msp430f5335", "msp430f5336", "msp430f5338", "msp430f5340", "msp430f5341",
144 "msp430f5342", "msp430f5358", "msp430f5359", "msp430f5418", "msp430f5418a",
145 "msp430f5419", "msp430f5419a", "msp430f5435", "msp430f5435a", "msp430f5436",
146 "msp430f5436a", "msp430f5437", "msp430f5437a", "msp430f5438", "msp430f5438a",
147 "msp430f5500", "msp430f5501", "msp430f5502", "msp430f5503", "msp430f5504",
148 "msp430f5505", "msp430f5506", "msp430f5507", "msp430f5508", "msp430f5509",
149 "msp430f5510", "msp430f5513", "msp430f5514", "msp430f5515", "msp430f5517",
150 "msp430f5519", "msp430f5521", "msp430f5522", "msp430f5524", "msp430f5525",
151 "msp430f5526", "msp430f5527", "msp430f5528", "msp430f5529", "msp430f5630",
152 "msp430f5631", "msp430f5632", "msp430f5633", "msp430f5634", "msp430f5635",
153 "msp430f5636", "msp430f5637", "msp430f5638", "msp430f5658", "msp430f5659",
154 "msp430f6433", "msp430f6435", "msp430f6436", "msp430f6438", "msp430f6458",
155 "msp430f6459", "msp430f6630", "msp430f6631", "msp430f6632", "msp430f6633",
156 "msp430f6634", "msp430f6635", "msp430f6636", "msp430f6637", "msp430f6638",
157 "msp430f6658", "msp430f6659", "msp430f6720", "msp430f6721", "msp430f6723",
158 "msp430f6724", "msp430f6725", "msp430f6726", "msp430f6730", "msp430f6731",
159 "msp430f6733", "msp430f6734", "msp430f6735", "msp430f6736", "msp430f6745",
160 "msp430f67451", "msp430f6746", "msp430f67461", "msp430f6747", "msp430f67471",
161 "msp430f6748", "msp430f67481", "msp430f6749", "msp430f67491", "msp430f6765",
162 "msp430f67651", "msp430f6766", "msp430f67661", "msp430f6767", "msp430f67671",
163 "msp430f6768", "msp430f67681", "msp430f6769", "msp430f67691", "msp430f6775",
164 "msp430f67751", "msp430f6776", "msp430f67761", "msp430f6777", "msp430f67771",
165 "msp430f6778", "msp430f67781", "msp430f6779", "msp430f67791", "msp430fg4616",
166 "msp430fg4617", "msp430fg4618", "msp430fg4619", "msp430fr5720", "msp430fr5721",
167 "msp430fr5722", "msp430fr5723", "msp430fr5724", "msp430fr5725", "msp430fr5726",
168 "msp430fr5727", "msp430fr5728", "msp430fr5729", "msp430fr5730", "msp430fr5731",
169 "msp430fr5732", "msp430fr5733", "msp430fr5734", "msp430fr5735", "msp430fr5736",
170 "msp430fr5737", "msp430fr5738", "msp430fr5739", "msp430fr5949", "msp430fr5969",
171 "msp430sl5438a","msp430x241x", "msp430x26x", "msp430x461x1", "msp430x46x",
172 "msp430x471x3", "msp430x471x6", "msp430x471x7", "msp430xg46x"
175 /* Generate a C preprocessor symbol based upon the MCU selected by the user.
176 If a specific MCU has not been selected then return a generic symbol instead. */
178 const char *
179 msp430_mcu_name (void)
181 if (target_mcu)
183 unsigned int i;
184 static char mcu_name [64];
186 snprintf (mcu_name, sizeof (mcu_name) - 1, "__%s__", target_mcu);
187 for (i = strlen (mcu_name); i--;)
188 mcu_name[i] = TOUPPER (mcu_name[i]);
189 return mcu_name;
192 return msp430x ? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
195 static void
196 msp430_option_override (void)
198 init_machine_status = msp430_init_machine_status;
200 if (target_cpu)
202 if (strcasecmp (target_cpu, "msp430x") == 0
203 || strcasecmp (target_cpu, "msp430xv2") == 0)
204 msp430x = true;
207 if (target_mcu)
209 unsigned i;
211 for (i = ARRAY_SIZE (msp430x_names); i--;)
212 if (strcasecmp (target_mcu, msp430x_names[i]) == 0)
214 msp430x = true;
215 break;
217 /* Note - it is not an error if we did not recognize the MCU
218 name. The msp430x_names array only contains those MCU names
219 which are currently known to use the MSP430X ISA. There are
220 lots of other MCUs which just use the MSP430 ISA. */
222 /* We also recognise two generic MCU 430X names. They do not
223 appear in the msp430x_names table as we want to be able to
224 generate special C preprocessor defines for them. That is
225 why we set target_mcu to NULL. */
226 if (strcasecmp (target_mcu, "msp430x") == 0
227 || strcasecmp (target_mcu, "msp430xv2") == 0)
229 msp430x = true;
230 target_mcu = NULL;
234 if (TARGET_LARGE && !msp430x)
235 error ("-mlarge requires a 430X-compatible -mmcu=");
237 if (flag_exceptions || flag_non_call_exceptions
238 || flag_unwind_tables || flag_asynchronous_unwind_tables)
239 flag_omit_frame_pointer = false;
240 else
241 flag_omit_frame_pointer = true;
243 /* This is a hack to work around a problem with the newlib build
244 mechanism. Newlib always appends CFLAGS to the end of the GCC
245 command line and always sets -O2 in CFLAGS. Thus it is not
246 possible to build newlib with -Os enabled. Until now... */
247 if (TARGET_OPT_SPACE && optimize < 3)
248 optimize_size = 1;
253 /* Storage Layout */
255 #undef TARGET_MS_BITFIELD_LAYOUT_P
256 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
258 bool
259 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED)
261 return false;
266 /* Register Usage */
268 /* Implements HARD_REGNO_NREGS. MSP430X registers can hold a single
269 PSImode value, but not an SImode value. */
271 msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED,
272 enum machine_mode mode)
274 if (mode == PSImode && msp430x)
275 return 1;
276 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
277 / UNITS_PER_WORD);
280 /* Implements HARD_REGNO_MODE_OK. */
282 msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED,
283 enum machine_mode mode)
285 return regno <= (ARG_POINTER_REGNUM - msp430_hard_regno_nregs (regno, mode));
288 /* Implements MODES_TIEABLE_P. */
289 bool
290 msp430_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
292 if ((mode1 == PSImode || mode2 == SImode)
293 || (mode1 == SImode || mode2 == PSImode))
294 return false;
296 return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
297 || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
298 == (GET_MODE_CLASS (mode2) == MODE_FLOAT
299 || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
302 #undef TARGET_FRAME_POINTER_REQUIRED
303 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
305 static bool
306 msp430_frame_pointer_required (void)
308 return false;
311 #undef TARGET_CAN_ELIMINATE
312 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
314 static bool
315 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED,
316 const int to_reg ATTRIBUTE_UNUSED)
318 return true;
321 /* Implements INITIAL_ELIMINATION_OFFSET. */
323 msp430_initial_elimination_offset (int from, int to)
325 int rv = 0; /* As if arg to arg. */
327 msp430_compute_frame_info ();
329 switch (to)
331 case STACK_POINTER_REGNUM:
332 rv += cfun->machine->framesize_outgoing;
333 rv += cfun->machine->framesize_locals;
334 /* Fall through. */
335 case FRAME_POINTER_REGNUM:
336 rv += cfun->machine->framesize_regs;
337 /* Allow for the saved return address. */
338 rv += (TARGET_LARGE ? 4 : 2);
339 /* NB/ No need to allow for crtl->args.pretend_args_size.
340 GCC does that for us. */
341 break;
342 default:
343 gcc_unreachable ();
346 switch (from)
348 case FRAME_POINTER_REGNUM:
349 /* Allow for the fall through above. */
350 rv -= (TARGET_LARGE ? 4 : 2);
351 rv -= cfun->machine->framesize_regs;
352 case ARG_POINTER_REGNUM:
353 break;
354 default:
355 gcc_unreachable ();
358 return rv;
361 /* Named Address Space support */
364 /* Return the appropriate mode for a named address pointer. */
365 #undef TARGET_ADDR_SPACE_POINTER_MODE
366 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
367 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
368 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
370 static enum machine_mode
371 msp430_addr_space_pointer_mode (addr_space_t addrspace)
373 switch (addrspace)
375 default:
376 case ADDR_SPACE_GENERIC:
377 return Pmode;
378 case ADDR_SPACE_NEAR:
379 return HImode;
380 case ADDR_SPACE_FAR:
381 return PSImode;
385 /* Function pointers are stored in unwind_word sized
386 variables, so make sure that unwind_word is big enough. */
387 #undef TARGET_UNWIND_WORD_MODE
388 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
390 static enum machine_mode
391 msp430_unwind_word_mode (void)
393 return TARGET_LARGE ? SImode : HImode;
396 /* Determine if one named address space is a subset of another. */
397 #undef TARGET_ADDR_SPACE_SUBSET_P
398 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
399 static bool
400 msp430_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
402 if (subset == superset)
403 return true;
404 else
405 return (subset != ADDR_SPACE_FAR && superset == ADDR_SPACE_FAR);
408 #undef TARGET_ADDR_SPACE_CONVERT
409 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
410 /* Convert from one address space to another. */
411 static rtx
412 msp430_addr_space_convert (rtx op, tree from_type, tree to_type)
414 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
415 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
416 rtx result;
418 if (to_as != ADDR_SPACE_FAR && from_as == ADDR_SPACE_FAR)
420 /* This is unpredictable, as we're truncating off usable address
421 bits. */
423 if (CONSTANT_P (op))
424 return gen_rtx_CONST (HImode, op);
426 result = gen_reg_rtx (HImode);
427 emit_insn (gen_truncpsihi2 (result, op));
428 return result;
430 else if (to_as == ADDR_SPACE_FAR && from_as != ADDR_SPACE_FAR)
432 /* This always works. */
434 if (CONSTANT_P (op))
435 return gen_rtx_CONST (PSImode, op);
437 result = gen_reg_rtx (PSImode);
438 emit_insn (gen_zero_extendhipsi2 (result, op));
439 return result;
441 else
442 gcc_unreachable ();
445 /* Stack Layout and Calling Conventions. */
447 /* For each function, we list the gcc version and the TI version on
448 each line, where we're converting the function names. */
449 static char const * const special_convention_function_names [] =
451 "__muldi3", "__mspabi_mpyll",
452 "__udivdi3", "__mspabi_divull",
453 "__umoddi3", "__mspabi_remull",
454 "__divdi3", "__mspabi_divlli",
455 "__moddi3", "__mspabi_remlli",
456 "__mspabi_srall",
457 "__mspabi_srlll",
458 "__mspabi_sllll",
459 "__adddf3", "__mspabi_addd",
460 "__subdf3", "__mspabi_subd",
461 "__muldf3", "__mspabi_mpyd",
462 "__divdf3", "__mspabi_divd",
463 "__mspabi_cmpd",
464 NULL
467 /* TRUE if the function passed is a "speical" function. Special
468 functions pass two DImode parameters in registers. */
469 static bool
470 msp430_special_register_convention_p (const char *name)
472 int i;
474 for (i = 0; special_convention_function_names [i]; i++)
475 if (! strcmp (name, special_convention_function_names [i]))
476 return true;
478 return false;
481 #undef TARGET_FUNCTION_VALUE_REGNO_P
482 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
484 bool
485 msp430_function_value_regno_p (unsigned int regno)
487 return regno == 12;
491 #undef TARGET_FUNCTION_VALUE
492 #define TARGET_FUNCTION_VALUE msp430_function_value
495 msp430_function_value (const_tree ret_type,
496 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
497 bool outgoing ATTRIBUTE_UNUSED)
499 return gen_rtx_REG (TYPE_MODE (ret_type), 12);
502 #undef TARGET_LIBCALL_VALUE
503 #define TARGET_LIBCALL_VALUE msp430_libcall_value
506 msp430_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
508 return gen_rtx_REG (mode, 12);
511 /* Implements INIT_CUMULATIVE_ARGS. */
512 void
513 msp430_init_cumulative_args (CUMULATIVE_ARGS *ca,
514 tree fntype ATTRIBUTE_UNUSED,
515 rtx libname ATTRIBUTE_UNUSED,
516 tree fndecl ATTRIBUTE_UNUSED,
517 int n_named_args ATTRIBUTE_UNUSED)
519 const char *fname;
520 memset (ca, 0, sizeof(*ca));
522 ca->can_split = 1;
524 if (fndecl)
525 fname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
526 else if (libname)
527 fname = XSTR (libname, 0);
528 else
529 fname = NULL;
531 if (fname && msp430_special_register_convention_p (fname))
532 ca->special_p = 1;
535 /* Helper function for argument passing; this function is the common
536 code that determines where an argument will be passed. */
537 static void
538 msp430_evaluate_arg (cumulative_args_t cap,
539 enum machine_mode mode,
540 const_tree type ATTRIBUTE_UNUSED,
541 bool named)
543 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
544 int nregs = GET_MODE_SIZE (mode);
545 int i;
547 ca->reg_count = 0;
548 ca->mem_count = 0;
550 if (!named)
551 return;
553 if (mode == PSImode)
554 nregs = 1;
555 else
556 nregs = (nregs + 1) / 2;
558 if (ca->special_p)
560 /* Function is passed two DImode operands, in R8:R11 and
561 R12:15. */
562 ca->start_reg = 8;
563 ca->reg_count = 4;
564 return;
567 switch (nregs)
569 case 1:
570 for (i = 0; i < 4; i++)
571 if (! ca->reg_used [i])
573 ca->reg_count = 1;
574 ca->start_reg = CA_FIRST_REG + i;
575 return;
577 break;
578 case 2:
579 for (i = 0; i < 3; i++)
580 if (! ca->reg_used [i] && ! ca->reg_used [i + 1])
582 ca->reg_count = 2;
583 ca->start_reg = CA_FIRST_REG + i;
584 return;
586 if (! ca->reg_used [3] && ca->can_split)
588 ca->reg_count = 1;
589 ca->mem_count = 2;
590 ca->start_reg = CA_FIRST_REG + 3;
591 return;
593 break;
594 case 3:
595 case 4:
596 ca->can_split = 0;
597 if (! ca->reg_used [0]
598 && ! ca->reg_used [1]
599 && ! ca->reg_used [2]
600 && ! ca->reg_used [3])
602 ca->reg_count = 4;
603 ca->start_reg = CA_FIRST_REG;
604 return;
606 break;
610 #undef TARGET_PROMOTE_PROTOTYPES
611 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
613 bool
614 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED)
616 return false;
619 #undef TARGET_FUNCTION_ARG
620 #define TARGET_FUNCTION_ARG msp430_function_arg
623 msp430_function_arg (cumulative_args_t cap,
624 enum machine_mode mode,
625 const_tree type,
626 bool named)
628 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
630 msp430_evaluate_arg (cap, mode, type, named);
632 if (ca->reg_count)
633 return gen_rtx_REG (mode, ca->start_reg);
635 return 0;
638 #undef TARGET_ARG_PARTIAL_BYTES
639 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
642 msp430_arg_partial_bytes (cumulative_args_t cap,
643 enum machine_mode mode,
644 tree type,
645 bool named)
647 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
649 msp430_evaluate_arg (cap, mode, type, named);
651 if (ca->reg_count && ca->mem_count)
652 return ca->reg_count * UNITS_PER_WORD;
654 return 0;
657 #undef TARGET_PASS_BY_REFERENCE
658 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
660 static bool
661 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED,
662 enum machine_mode mode,
663 const_tree type,
664 bool named ATTRIBUTE_UNUSED)
666 return (mode == BLKmode
667 || (type && TREE_CODE (type) == RECORD_TYPE)
668 || (type && TREE_CODE (type) == UNION_TYPE));
671 #undef TARGET_CALLEE_COPIES
672 #define TARGET_CALLEE_COPIES msp430_callee_copies
674 static bool
675 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED,
676 enum machine_mode mode ATTRIBUTE_UNUSED,
677 const_tree type ATTRIBUTE_UNUSED,
678 bool named ATTRIBUTE_UNUSED)
680 return true;
683 #undef TARGET_FUNCTION_ARG_ADVANCE
684 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
686 void
687 msp430_function_arg_advance (cumulative_args_t cap,
688 enum machine_mode mode,
689 const_tree type,
690 bool named)
692 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
693 int i;
695 msp430_evaluate_arg (cap, mode, type, named);
697 if (ca->start_reg >= CA_FIRST_REG)
698 for (i = 0; i < ca->reg_count; i ++)
699 ca->reg_used [i + ca->start_reg - CA_FIRST_REG] = 1;
701 ca->special_p = 0;
704 #undef TARGET_FUNCTION_ARG_BOUNDARY
705 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
707 static unsigned int
708 msp430_function_arg_boundary (enum machine_mode mode, const_tree type)
710 if (mode == BLKmode
711 && int_size_in_bytes (type) > 1)
712 return 16;
713 if (GET_MODE_BITSIZE (mode) > 8)
714 return 16;
715 return 8;
718 #undef TARGET_RETURN_IN_MEMORY
719 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
721 static bool
722 msp430_return_in_memory (const_tree ret_type, const_tree fntype ATTRIBUTE_UNUSED)
724 enum machine_mode mode = TYPE_MODE (ret_type);
726 if (mode == BLKmode
727 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == RECORD_TYPE)
728 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == UNION_TYPE))
729 return true;
731 if (GET_MODE_SIZE (mode) > 8)
732 return true;
734 return false;
737 #undef TARGET_GET_RAW_ARG_MODE
738 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
740 static enum machine_mode
741 msp430_get_raw_arg_mode (int regno)
743 return (regno == ARG_POINTER_REGNUM) ? VOIDmode : Pmode;
746 #undef TARGET_GET_RAW_RESULT_MODE
747 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
749 static enum machine_mode
750 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED)
752 return Pmode;
755 /* Addressing Modes */
757 #undef TARGET_LEGITIMATE_ADDRESS_P
758 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
760 static bool
761 reg_ok_for_addr (rtx r, bool strict)
763 int rn = REGNO (r);
765 if (strict && rn >= FIRST_PSEUDO_REGISTER)
766 rn = reg_renumber [rn];
767 if (strict && 0 <= rn && rn < FIRST_PSEUDO_REGISTER)
768 return true;
769 if (!strict)
770 return true;
771 return false;
774 bool
775 msp430_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
776 rtx x ATTRIBUTE_UNUSED,
777 bool strict ATTRIBUTE_UNUSED)
779 switch (GET_CODE (x))
781 case MEM:
782 return false;
784 case PLUS:
785 if (REG_P (XEXP (x, 0)))
787 if (GET_MODE (x) != GET_MODE (XEXP (x, 0)))
788 return false;
789 if (!reg_ok_for_addr (XEXP (x, 0), strict))
790 return false;
791 switch (GET_CODE (XEXP (x, 1)))
793 case CONST:
794 case SYMBOL_REF:
795 case CONST_INT:
796 return true;
797 default:
798 return false;
801 return false;
803 case REG:
804 if (!reg_ok_for_addr (x, strict))
805 return false;
806 /* else... */
807 case CONST:
808 case SYMBOL_REF:
809 case CONST_INT:
810 return true;
812 default:
813 return false;
817 #undef TARGET_LEGITIMATE_CONSTANT_P
818 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
820 static bool
821 msp430_legitimate_constant (enum machine_mode mode, rtx x)
823 return ! CONST_INT_P (x)
824 || mode != PSImode
825 /* GCC does not know the width of the PSImode, so make
826 sure that it does not try to use a constant value that
827 is out of range. */
828 || (INTVAL (x) < (1 << 20) && INTVAL (x) >= (-1 << 20));
832 #undef TARGET_RTX_COSTS
833 #define TARGET_RTX_COSTS msp430_rtx_costs
835 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED,
836 int code,
837 int outer_code ATTRIBUTE_UNUSED,
838 int opno ATTRIBUTE_UNUSED,
839 int * total,
840 bool speed ATTRIBUTE_UNUSED)
842 switch (code)
844 case SIGN_EXTEND:
845 if (GET_MODE (x) == SImode && outer_code == SET)
847 *total = COSTS_N_INSNS (4);
848 return true;
850 break;
851 case ASHIFT:
852 case ASHIFTRT:
853 case LSHIFTRT:
854 if (!msp430x)
856 *total = COSTS_N_INSNS (100);
857 return true;
859 break;
861 return false;
864 /* Function Entry and Exit */
866 /* The MSP430 call frame looks like this:
868 <higher addresses>
869 +--------------------+
871 | Stack Arguments |
873 +--------------------+ <-- "arg pointer"
875 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
877 +--------------------+
878 | SR if this func has|
879 | been called via an |
880 | interrupt. |
881 +--------------------+ <-- SP before prologue, also AP
883 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
885 +--------------------+ <-- "frame pointer"
887 | Locals |
889 +--------------------+
891 | Outgoing Args |
893 +--------------------+ <-- SP during function
894 <lower addresses>
898 /* We use this to wrap all emitted insns in the prologue, so they get
899 the "frame-related" (/f) flag set. */
900 static rtx
901 F (rtx x)
903 RTX_FRAME_RELATED_P (x) = 1;
904 return x;
907 /* This is the one spot that decides if a register is to be saved and
908 restored in the prologue/epilogue. */
909 static bool
910 msp430_preserve_reg_p (int regno)
912 /* PC, SP, SR, and the constant generator. */
913 if (regno <= 3)
914 return false;
916 /* FIXME: add interrupt, EH, etc. */
917 if (crtl->calls_eh_return)
918 return true;
920 /* Shouldn't be more than the above, but just in case... */
921 if (fixed_regs [regno])
922 return false;
924 /* Interrupt handlers save all registers they use, even
925 ones which are call saved. If they call other functions
926 then *every* register is saved. */
927 if (msp430_is_interrupt_func ())
928 return ! crtl->is_leaf || df_regs_ever_live_p (regno);
930 if (!call_used_regs [regno]
931 && df_regs_ever_live_p (regno))
932 return true;
934 return false;
937 /* Compute all the frame-related fields in our machine_function
938 structure. */
939 static void
940 msp430_compute_frame_info (void)
942 int i;
944 cfun->machine->computed = 1;
945 cfun->machine->framesize_regs = 0;
946 cfun->machine->framesize_locals = get_frame_size ();
947 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
949 for (i = 0; i < ARG_POINTER_REGNUM; i ++)
950 if (msp430_preserve_reg_p (i))
952 cfun->machine->need_to_save [i] = 1;
953 cfun->machine->framesize_regs += (TARGET_LARGE ? 4 : 2);
955 else
956 cfun->machine->need_to_save [i] = 0;
958 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
959 cfun->machine->framesize_locals ++;
961 cfun->machine->framesize = (cfun->machine->framesize_regs
962 + cfun->machine->framesize_locals
963 + cfun->machine->framesize_outgoing);
966 static inline bool
967 is_attr_func (const char * attr)
969 return lookup_attribute (attr, DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE;
972 /* Returns true if the current function has the "interrupt" attribute. */
974 bool
975 msp430_is_interrupt_func (void)
977 return is_attr_func ("interrupt");
980 static bool
981 is_wakeup_func (void)
983 return msp430_is_interrupt_func () && is_attr_func ("wakeup");
986 static inline bool
987 is_naked_func (void)
989 return is_attr_func ("naked");
992 static inline bool
993 is_reentrant_func (void)
995 return is_attr_func ("reentrant");
998 static inline bool
999 is_critical_func (void)
1001 return is_attr_func ("critical");
1004 #undef TARGET_ASM_FUNCTION_PROLOGUE
1005 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
1007 static void
1008 msp430_start_function (FILE *outfile, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
1010 int r, n;
1012 fprintf (outfile, "; start of function\n");
1014 if (DECL_ATTRIBUTES (current_function_decl) != NULL_TREE)
1016 fprintf (outfile, "; attributes: ");
1017 if (is_naked_func ())
1018 fprintf (outfile, "naked ");
1019 if (msp430_is_interrupt_func ())
1020 fprintf (outfile, "interrupt ");
1021 if (is_reentrant_func ())
1022 fprintf (outfile, "reentrant ");
1023 if (is_critical_func ())
1024 fprintf (outfile, "critical ");
1025 if (is_wakeup_func ())
1026 fprintf (outfile, "wakeup ");
1027 fprintf (outfile, "\n");
1030 fprintf (outfile, "; framesize_regs: %d\n", cfun->machine->framesize_regs);
1031 fprintf (outfile, "; framesize_locals: %d\n", cfun->machine->framesize_locals);
1032 fprintf (outfile, "; framesize_outgoing: %d\n", cfun->machine->framesize_outgoing);
1033 fprintf (outfile, "; framesize: %d\n", cfun->machine->framesize);
1034 fprintf (outfile, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM));
1035 fprintf (outfile, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM));
1037 n = 0;
1038 fprintf (outfile, "; saved regs:");
1039 for (r = 0; r < ARG_POINTER_REGNUM; r++)
1040 if (cfun->machine->need_to_save [r])
1042 fprintf (outfile, " %s", reg_names [r]);
1043 n = 1;
1045 if (n == 0)
1046 fprintf (outfile, "(none)");
1047 fprintf (outfile, "\n");
1050 /* Common code to change the stack pointer. */
1051 static void
1052 increment_stack (HOST_WIDE_INT amount)
1054 rtx inc;
1055 rtx sp = stack_pointer_rtx;
1057 if (amount == 0)
1058 return;
1060 if (amount < 0)
1062 inc = GEN_INT (- amount);
1063 if (TARGET_LARGE)
1064 F (emit_insn (gen_subpsi3 (sp, sp, inc)));
1065 else
1066 F (emit_insn (gen_subhi3 (sp, sp, inc)));
1068 else
1070 inc = GEN_INT (amount);
1071 if (TARGET_LARGE)
1072 emit_insn (gen_addpsi3 (sp, sp, inc));
1073 else
1074 emit_insn (gen_addhi3 (sp, sp, inc));
1078 /* Verify MSP430 specific attributes. */
1080 static tree
1081 msp430_attr (tree * node,
1082 tree name,
1083 tree args,
1084 int flags ATTRIBUTE_UNUSED,
1085 bool * no_add_attrs)
1087 gcc_assert (DECL_P (* node));
1089 if (args != NULL)
1091 tree value = TREE_VALUE (args);
1093 switch (TREE_CODE (value))
1095 case STRING_CST:
1096 if ( strcmp (TREE_STRING_POINTER (value), "reset")
1097 && strcmp (TREE_STRING_POINTER (value), "nmi")
1098 && strcmp (TREE_STRING_POINTER (value), "watchdog"))
1099 /* Allow the attribute to be added - the linker script
1100 being used may still recognise this name. */
1101 warning (OPT_Wattributes,
1102 "unrecognised interrupt vector argument of %qE attribute",
1103 name);
1104 break;
1106 case INTEGER_CST:
1107 if (TREE_INT_CST_LOW (value) > 63)
1108 /* Allow the attribute to be added - the linker script
1109 being used may still recognise this value. */
1110 warning (OPT_Wattributes,
1111 "numeric argument of %qE attribute must be in range 0..63",
1112 name);
1113 break;
1115 default:
1116 warning (OPT_Wattributes,
1117 "argument of %qE attribute is not a string constant or number",
1118 name);
1119 *no_add_attrs = true;
1120 break;
1124 if (TREE_CODE (* node) != FUNCTION_DECL)
1126 warning (OPT_Wattributes,
1127 "%qE attribute only applies to functions",
1128 name);
1129 * no_add_attrs = true;
1132 /* FIXME: We ought to check that the interrupt handler
1133 attribute has been applied to a void function. */
1134 /* FIXME: We should check that reentrant and critical
1135 functions are not naked and that critical functions
1136 are not reentrant. */
1138 return NULL_TREE;
1141 #undef TARGET_ATTRIBUTE_TABLE
1142 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
1144 /* Table of MSP430-specific attributes. */
1145 const struct attribute_spec msp430_attribute_table[] =
1147 /* Name min_len decl_req, fn_type_req, affects_type_identity
1148 max_len, type_req, handler. */
1149 { "interrupt", 0, 1, true, false, false, msp430_attr, false },
1150 { "naked", 0, 0, true, false, false, msp430_attr, false },
1151 { "reentrant", 0, 0, true, false, false, msp430_attr, false },
1152 { "critical", 0, 0, true, false, false, msp430_attr, false },
1153 { "wakeup", 0, 0, true, false, false, msp430_attr, false },
1154 { NULL, 0, 0, false, false, false, NULL, false }
1157 void
1158 msp430_start_function (FILE *file, const char *name, tree decl)
1160 tree int_attr;
1162 int_attr = lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl));
1163 if (int_attr != NULL_TREE)
1165 tree intr_vector = TREE_VALUE (int_attr);
1167 if (intr_vector != NULL_TREE)
1169 char buf[101];
1171 intr_vector = TREE_VALUE (intr_vector);
1173 /* The interrupt attribute has a vector value. Turn this into a
1174 section name, switch to that section and put the address of
1175 the current function into that vector slot. Note msp430_attr()
1176 has already verified the vector name for us. */
1177 if (TREE_CODE (intr_vector) == STRING_CST)
1178 sprintf (buf, "__interrupt_vector_%.80s",
1179 TREE_STRING_POINTER (intr_vector));
1180 else /* TREE_CODE (intr_vector) == INTEGER_CST */
1181 sprintf (buf, "__interrupt_vector_%u",
1182 (unsigned int) TREE_INT_CST_LOW (intr_vector));
1184 switch_to_section (get_section (buf, SECTION_CODE, decl));
1185 fputs ("\t.word\t", file);
1186 assemble_name (file, name);
1187 fputc ('\n', file);
1188 fputc ('\t', file);
1192 switch_to_section (function_section (decl));
1193 ASM_OUTPUT_FUNCTION_LABEL (file, name, decl);
1196 static section *
1197 msp430_function_section (tree decl, enum node_frequency freq, bool startup, bool exit)
1199 /* In large mode we must make sure that interrupt handlers are put into
1200 low memory as the vector table only accepts 16-bit addresses. */
1201 if (TARGET_LARGE
1202 && lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl)))
1203 return get_section (".lowtext", SECTION_CODE | SECTION_WRITE , decl);
1205 /* Otherwise, use the default function section. */
1206 return default_function_section (decl, freq, startup, exit);
1209 #undef TARGET_ASM_FUNCTION_SECTION
1210 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
1212 enum msp430_builtin
1214 MSP430_BUILTIN_BIC_SR,
1215 MSP430_BUILTIN_BIS_SR,
1216 MSP430_BUILTIN_max
1219 static GTY(()) tree msp430_builtins [(int) MSP430_BUILTIN_max];
1221 static void
1222 msp430_init_builtins (void)
1224 tree void_ftype_int = build_function_type_list (void_type_node, integer_type_node, NULL);
1226 msp430_builtins[MSP430_BUILTIN_BIC_SR] =
1227 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int,
1228 MSP430_BUILTIN_BIC_SR, BUILT_IN_MD, NULL, NULL_TREE);
1230 msp430_builtins[MSP430_BUILTIN_BIS_SR] =
1231 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int,
1232 MSP430_BUILTIN_BIS_SR, BUILT_IN_MD, NULL, NULL_TREE);
1235 static tree
1236 msp430_builtin_decl (unsigned code, bool initialize ATTRIBUTE_UNUSED)
1238 switch (code)
1240 case MSP430_BUILTIN_BIC_SR:
1241 case MSP430_BUILTIN_BIS_SR:
1242 return msp430_builtins[code];
1243 default:
1244 return error_mark_node;
1248 static rtx
1249 msp430_expand_builtin (tree exp,
1250 rtx target ATTRIBUTE_UNUSED,
1251 rtx subtarget ATTRIBUTE_UNUSED,
1252 enum machine_mode mode ATTRIBUTE_UNUSED,
1253 int ignore ATTRIBUTE_UNUSED)
1255 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
1256 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
1257 rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
1259 if (! msp430_is_interrupt_func ())
1261 error ("MSP430 builtin functions only work inside interrupt handlers");
1262 return NULL_RTX;
1265 if (! REG_P (arg1) && ! CONSTANT_P (arg1))
1266 arg1 = force_reg (mode, arg1);
1268 switch (fcode)
1270 case MSP430_BUILTIN_BIC_SR: emit_insn (gen_bic_SR (arg1)); break;
1271 case MSP430_BUILTIN_BIS_SR: emit_insn (gen_bis_SR (arg1)); break;
1272 default:
1273 internal_error ("bad builtin code");
1274 break;
1276 return NULL_RTX;
1279 #undef TARGET_INIT_BUILTINS
1280 #define TARGET_INIT_BUILTINS msp430_init_builtins
1282 #undef TARGET_EXPAND_BUILTIN
1283 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
1285 #undef TARGET_BUILTIN_DECL
1286 #define TARGET_BUILTIN_DECL msp430_builtin_decl
1288 void
1289 msp430_expand_prologue (void)
1291 int i, j;
1292 int fs;
1293 /* Always use stack_pointer_rtx instead of calling
1294 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
1295 that there is a single rtx representing the stack pointer,
1296 namely stack_pointer_rtx, and uses == to recognize it. */
1297 rtx sp = stack_pointer_rtx;
1298 rtx p;
1300 if (is_naked_func ())
1301 return;
1303 emit_insn (gen_prologue_start_marker ());
1305 if (is_critical_func ())
1307 emit_insn (gen_push_intr_state ());
1308 emit_insn (gen_disable_interrupts ());
1310 else if (is_reentrant_func ())
1311 emit_insn (gen_disable_interrupts ());
1313 if (!cfun->machine->computed)
1314 msp430_compute_frame_info ();
1316 if (flag_stack_usage_info)
1317 current_function_static_stack_size = cfun->machine->framesize;
1319 if (crtl->args.pretend_args_size)
1321 rtx note;
1323 gcc_assert (crtl->args.pretend_args_size == 2);
1325 p = emit_insn (gen_grow_and_swap ());
1327 /* Document the stack decrement... */
1328 note = F (gen_rtx_SET (Pmode, stack_pointer_rtx,
1329 gen_rtx_MINUS (Pmode, stack_pointer_rtx, GEN_INT (2))));
1330 add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
1332 /* ...and the establishment of a new location for the return address. */
1333 note = F (gen_rtx_SET (Pmode, gen_rtx_MEM (Pmode,
1334 gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-2))),
1335 pc_rtx));
1336 add_reg_note (p, REG_CFA_OFFSET, note);
1337 F (p);
1340 for (i = 15; i >= 4; i--)
1341 if (cfun->machine->need_to_save [i])
1343 int seq, count;
1344 rtx note;
1346 for (seq = i - 1; seq >= 4 && cfun->machine->need_to_save[seq]; seq --)
1348 count = i - seq;
1350 if (msp430x)
1352 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
1353 p = F (emit_insn (gen_pushm (gen_rtx_REG (Pmode, i),
1354 GEN_INT (count))));
1356 note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1));
1358 XVECEXP (note, 0, 0)
1359 = F (gen_rtx_SET (VOIDmode,
1360 stack_pointer_rtx,
1361 gen_rtx_PLUS (Pmode,
1362 stack_pointer_rtx,
1363 GEN_INT (count * (TARGET_LARGE ? -4 : -2)))));
1365 /* *sp-- = R[i-j] */
1366 /* sp+N R10
1368 sp R4 */
1369 for (j = 0; j < count; j ++)
1371 rtx addr;
1372 int ofs = (count - j - 1) * (TARGET_LARGE ? 4 : 2);
1374 if (ofs)
1375 addr = gen_rtx_PLUS (Pmode, sp, GEN_INT (ofs));
1376 else
1377 addr = stack_pointer_rtx;
1379 XVECEXP (note, 0, j + 1) =
1380 F (gen_rtx_SET (VOIDmode,
1381 gen_rtx_MEM (Pmode, addr),
1382 gen_rtx_REG (Pmode, i - j)) );
1385 add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
1386 i -= count - 1;
1388 else
1389 F (emit_insn (gen_push (gen_rtx_REG (Pmode, i))));
1392 if (frame_pointer_needed)
1393 F (emit_move_insn (gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM), sp));
1395 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1397 increment_stack (- fs);
1399 emit_insn (gen_prologue_end_marker ());
1402 void
1403 msp430_expand_epilogue (int is_eh)
1405 int i;
1406 int fs;
1407 int helper_n = 0;
1409 if (is_naked_func ())
1410 return;
1412 if (cfun->machine->need_to_save [10])
1414 /* Check for a helper function. */
1415 helper_n = 7; /* For when the loop below never sees a match. */
1416 for (i = 9; i >= 4; i--)
1417 if (!cfun->machine->need_to_save [i])
1419 helper_n = 10 - i;
1420 for (; i >= 4; i--)
1421 if (cfun->machine->need_to_save [i])
1423 helper_n = 0;
1424 break;
1426 break;
1430 emit_insn (gen_epilogue_start_marker ());
1432 if (cfun->decl && strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun->decl)), "main") == 0)
1433 emit_insn (gen_msp430_refsym_need_exit ());
1435 if (is_wakeup_func ())
1436 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
1437 status register current residing on the stack. When this function
1438 executes its RETI instruction the SR will be updated with this saved
1439 value, thus ensuring that the processor is woken up from any low power
1440 state in which it may be residing. */
1441 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
1443 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1445 increment_stack (fs);
1447 if (is_eh)
1449 /* We need to add the right "SP" register save just after the
1450 regular ones, so that when we pop it off we're in the EH
1451 return frame, not this one. This overwrites our own return
1452 address, but we're not going to be returning anyway. */
1453 rtx r12 = gen_rtx_REG (Pmode, 12);
1454 rtx (*addPmode)(rtx, rtx, rtx) = TARGET_LARGE ? gen_addpsi3 : gen_addhi3;
1456 /* R12 will hold the new SP. */
1457 i = cfun->machine->framesize_regs;
1458 emit_move_insn (r12, stack_pointer_rtx);
1459 emit_insn (addPmode (r12, r12, EH_RETURN_STACKADJ_RTX));
1460 emit_insn (addPmode (r12, r12, GEN_INT (i)));
1461 emit_move_insn (gen_rtx_MEM (Pmode, plus_constant (Pmode, stack_pointer_rtx, i)), r12);
1464 for (i = 4; i <= 15; i++)
1465 if (cfun->machine->need_to_save [i])
1467 int seq, count;
1469 for (seq = i + 1; seq <= 15 && cfun->machine->need_to_save[seq]; seq ++)
1471 count = seq - i;
1473 if (msp430x)
1475 /* Note: With TARGET_LARGE we still use
1476 POPM as POPX.A is two bytes bigger. */
1477 emit_insn (gen_popm (stack_pointer_rtx, GEN_INT (seq - 1),
1478 GEN_INT (count)));
1479 i += count - 1;
1481 else if (i == 11 - helper_n
1482 && ! msp430_is_interrupt_func ()
1483 && ! is_reentrant_func ()
1484 && ! is_critical_func ()
1485 && crtl->args.pretend_args_size == 0
1486 /* Calling the helper takes as many bytes as the POP;RET sequence. */
1487 && helper_n > 1
1488 && !is_eh)
1490 emit_insn (gen_epilogue_helper (GEN_INT (helper_n)));
1491 return;
1493 else
1494 emit_insn (gen_pop (gen_rtx_REG (Pmode, i)));
1497 if (is_eh)
1499 /* Also pop SP, which puts us into the EH return frame. Except
1500 that you can't "pop" sp, you have to just load it off the
1501 stack. */
1502 emit_move_insn (stack_pointer_rtx, gen_rtx_MEM (Pmode, stack_pointer_rtx));
1505 if (crtl->args.pretend_args_size)
1506 emit_insn (gen_swap_and_shrink ());
1508 if (is_critical_func ())
1509 emit_insn (gen_pop_intr_state ());
1510 else if (is_reentrant_func ())
1511 emit_insn (gen_enable_interrupts ());
1513 emit_jump_insn (gen_msp_return ());
1516 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
1517 m32c_emit_eh_epilogue. */
1519 msp430_eh_return_stackadj_rtx (void)
1521 if (!cfun->machine->eh_stack_adjust)
1523 rtx sa;
1525 sa = gen_rtx_REG (Pmode, 15);
1526 cfun->machine->eh_stack_adjust = sa;
1528 return cfun->machine->eh_stack_adjust;
1531 /* This function is called before reload, to "fix" the stack in
1532 preparation for an EH return. */
1533 void
1534 msp430_expand_eh_return (rtx eh_handler)
1536 /* These are all Pmode */
1537 rtx ap, sa, ra, tmp;
1539 ap = arg_pointer_rtx;
1540 sa = msp430_eh_return_stackadj_rtx ();
1541 ra = eh_handler;
1543 tmp = ap;
1544 tmp = gen_rtx_PLUS (Pmode, ap, sa);
1545 tmp = plus_constant (Pmode, tmp, TARGET_LARGE ? -4 : -2);
1546 tmp = gen_rtx_MEM (Pmode, tmp);
1547 emit_move_insn (tmp, ra);
1550 /* This is a list of MD patterns that implement fixed-count shifts. */
1551 static struct
1553 const char *name;
1554 int count;
1555 int need_430x;
1556 rtx (*genfunc)(rtx,rtx);
1558 const_shift_helpers[] =
1560 #define CSH(N,C,X,G) { "__mspabi_"N, C, X, gen_##G }
1562 CSH ("slli", 1, 1, slli_1),
1563 CSH ("slll", 1, 1, slll_1),
1564 CSH ("slll", 2, 1, slll_2),
1566 CSH ("srai", 1, 0, srai_1),
1567 CSH ("sral", 1, 0, sral_1),
1568 CSH ("sral", 2, 0, sral_2),
1570 CSH ("srll", 1, 0, srll_1),
1571 CSH ("srll", 2, 1, srll_2x),
1572 { 0, 0, 0, 0 }
1573 #undef CSH
1576 /* The MSP430 ABI defines a number of helper functions that should be
1577 used for, for example, 32-bit shifts. This function is called to
1578 emit such a function, using the table above to optimize some
1579 cases. */
1580 void
1581 msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variants)
1583 rtx c, f;
1584 char *helper_const = NULL;
1585 int arg2 = 13;
1586 int arg1sz = 1;
1587 enum machine_mode arg0mode = GET_MODE (operands[0]);
1588 enum machine_mode arg1mode = GET_MODE (operands[1]);
1589 enum machine_mode arg2mode = GET_MODE (operands[2]);
1590 int have_430x = msp430x ? 1 : 0;
1592 if (CONST_INT_P (operands[2]))
1594 int i;
1596 for (i=0; const_shift_helpers[i].name; i++)
1598 if (const_shift_helpers[i].need_430x <= have_430x
1599 && strcmp (helper_name, const_shift_helpers[i].name) == 0
1600 && INTVAL (operands[2]) == const_shift_helpers[i].count)
1602 emit_insn (const_shift_helpers[i].genfunc (operands[0], operands[1]));
1603 return;
1608 if (arg1mode == VOIDmode)
1609 arg1mode = arg0mode;
1610 if (arg2mode == VOIDmode)
1611 arg2mode = arg0mode;
1613 if (arg1mode == SImode)
1615 arg2 = 14;
1616 arg1sz = 2;
1619 if (const_variants
1620 && CONST_INT_P (operands[2])
1621 && INTVAL (operands[2]) >= 1
1622 && INTVAL (operands[2]) <= 15)
1624 /* Note that the INTVAL is limited in value and length by the conditional above. */
1625 int len = strlen (helper_name) + 4;
1626 helper_const = (char *) xmalloc (len);
1627 snprintf (helper_const, len, "%s_%d", helper_name, (int) INTVAL (operands[2]));
1630 emit_move_insn (gen_rtx_REG (arg1mode, 12),
1631 operands[1]);
1632 if (!helper_const)
1633 emit_move_insn (gen_rtx_REG (arg2mode, arg2),
1634 operands[2]);
1636 c = gen_call_value_internal (gen_rtx_REG (arg0mode, 12),
1637 gen_rtx_SYMBOL_REF (VOIDmode, helper_const ? helper_const : helper_name),
1638 GEN_INT (0));
1639 c = emit_call_insn (c);
1640 RTL_CONST_CALL_P (c) = 1;
1642 f = 0;
1643 use_regs (&f, 12, arg1sz);
1644 if (!helper_const)
1645 use_regs (&f, arg2, 1);
1646 add_function_usage_to (c, f);
1648 emit_move_insn (operands[0],
1649 gen_rtx_REG (arg0mode, 12));
1652 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
1653 void
1654 msp430_fixup_compare_operands (enum machine_mode my_mode, rtx * operands)
1656 /* constants we're looking for, not constants which are allowed. */
1657 int const_op_idx = 1;
1659 if (msp430_reversible_cmp_operator (operands[0], VOIDmode))
1660 const_op_idx = 2;
1662 if (GET_CODE (operands[const_op_idx]) != REG
1663 && GET_CODE (operands[const_op_idx]) != MEM)
1664 operands[const_op_idx] = copy_to_mode_reg (my_mode, operands[const_op_idx]);
1667 /* Simplify_gen_subreg() doesn't handle memory references the way we
1668 need it to below, so we use this function for when we must get a
1669 valid subreg in a "natural" state. */
1671 msp430_subreg (enum machine_mode mode, rtx r, enum machine_mode omode, int byte)
1673 rtx rv;
1675 if (GET_CODE (r) == SUBREG
1676 && SUBREG_BYTE (r) == 0)
1678 rtx ireg = SUBREG_REG (r);
1679 enum machine_mode imode = GET_MODE (ireg);
1681 /* special case for (HI (SI (PSI ...), 0)) */
1682 if (imode == PSImode
1683 && mode == HImode
1684 && byte == 0)
1685 rv = gen_rtx_SUBREG (mode, ireg, byte);
1686 else
1687 rv = simplify_gen_subreg (mode, ireg, imode, byte);
1689 else if (GET_CODE (r) == MEM)
1690 rv = adjust_address (r, mode, byte);
1691 else
1692 rv = simplify_gen_subreg (mode, r, omode, byte);
1694 if (!rv)
1695 gcc_unreachable ();
1697 return rv;
1700 /* Called by movsi_x to generate the HImode operands. */
1701 void
1702 msp430_split_movsi (rtx *operands)
1704 rtx op00, op02, op10, op12;
1706 op00 = msp430_subreg (HImode, operands[0], SImode, 0);
1707 op02 = msp430_subreg (HImode, operands[0], SImode, 2);
1709 if (GET_CODE (operands[1]) == CONST
1710 || GET_CODE (operands[1]) == SYMBOL_REF)
1712 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
1713 op10 = gen_rtx_CONST (HImode, op10);
1714 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
1715 op12 = gen_rtx_CONST (HImode, op12);
1717 else
1719 op10 = msp430_subreg (HImode, operands[1], SImode, 0);
1720 op12 = msp430_subreg (HImode, operands[1], SImode, 2);
1723 if (rtx_equal_p (operands[0], operands[1]))
1725 operands[2] = op02;
1726 operands[4] = op12;
1727 operands[3] = op00;
1728 operands[5] = op10;
1730 else if (rtx_equal_p (op00, op12)
1731 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
1732 || (REG_P (op00) && reg_mentioned_p (op00, op10))
1733 /* Or storing (rN) into mem (rN). */
1734 || (REG_P (op10) && reg_mentioned_p (op10, op00))
1737 operands[2] = op02;
1738 operands[4] = op12;
1739 operands[3] = op00;
1740 operands[5] = op10;
1742 else
1744 operands[2] = op00;
1745 operands[4] = op10;
1746 operands[3] = op02;
1747 operands[5] = op12;
1752 /* The MSPABI specifies the names of various helper functions, many of
1753 which are compatible with GCC's helpers. This table maps the GCC
1754 name to the MSPABI name. */
1755 static const struct
1757 char const * const gcc_name;
1758 char const * const ti_name;
1760 helper_function_name_mappings [] =
1762 /* Floating point to/from integer conversions. */
1763 { "__truncdfsf2", "__mspabi_cvtdf" },
1764 { "__extendsfdf2", "__mspabi_cvtfd" },
1765 { "__fixdfhi", "__mspabi_fixdi" },
1766 { "__fixdfsi", "__mspabi_fixdli" },
1767 { "__fixdfdi", "__mspabi_fixdlli" },
1768 { "__fixunsdfhi", "__mspabi_fixdu" },
1769 { "__fixunsdfsi", "__mspabi_fixdul" },
1770 { "__fixunsdfdi", "__mspabi_fixdull" },
1771 { "__fixsfhi", "__mspabi_fixfi" },
1772 { "__fixsfsi", "__mspabi_fixfli" },
1773 { "__fixsfdi", "__mspabi_fixflli" },
1774 { "__fixunsfhi", "__mspabi_fixfu" },
1775 { "__fixunsfsi", "__mspabi_fixful" },
1776 { "__fixunsfdi", "__mspabi_fixfull" },
1777 { "__floathisf", "__mspabi_fltif" },
1778 { "__floatsisf", "__mspabi_fltlif" },
1779 { "__floatdisf", "__mspabi_fltllif" },
1780 { "__floathidf", "__mspabi_fltid" },
1781 { "__floatsidf", "__mspabi_fltlid" },
1782 { "__floatdidf", "__mspabi_fltllid" },
1783 { "__floatunhisf", "__mspabi_fltuf" },
1784 { "__floatunsisf", "__mspabi_fltulf" },
1785 { "__floatundisf", "__mspabi_fltullf" },
1786 { "__floatunhidf", "__mspabi_fltud" },
1787 { "__floatunsidf", "__mspabi_fltuld" },
1788 { "__floatundidf", "__mspabi_fltulld" },
1790 /* Floating point comparisons. */
1791 /* GCC uses individual functions for each comparison, TI uses one
1792 compare <=> function. */
1794 /* Floating point arithmatic */
1795 { "__adddf3", "__mspabi_addd" },
1796 { "__addsf3", "__mspabi_addf" },
1797 { "__divdf3", "__mspabi_divd" },
1798 { "__divsf3", "__mspabi_divf" },
1799 { "__muldf3", "__mspabi_mpyd" },
1800 { "__mulsf3", "__mspabi_mpyf" },
1801 { "__subdf3", "__mspabi_subd" },
1802 { "__subsf3", "__mspabi_subf" },
1803 /* GCC does not use helper functions for negation */
1805 /* Integer multiply, divide, remainder. */
1806 /* Note: gcc doesn't know about hardware multiply options (yet?) */
1807 { "__mulhi3", "__mspabi_mpyi" },
1808 { "__mulsi3", "__mspabi_mpyl" },
1809 { "__muldi3", "__mspabi_mpyll" },
1810 #if 0
1811 /* Clarify signed vs unsigned first. */
1812 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
1813 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
1814 #endif
1816 { "__divhi3", "__mspabi_divi" },
1817 { "__divsi3", "__mspabi_divli" },
1818 { "__divdi3", "__mspabi_divlli" },
1819 { "__udivhi3", "__mspabi_divu" },
1820 { "__udivsi3", "__mspabi_divlu" },
1821 { "__udivdi3", "__mspabi_divllu" },
1822 { "__modhi3", "__mspabi_remi" },
1823 { "__modsi3", "__mspabi_remli" },
1824 { "__moddi3", "__mspabi_remlli" },
1825 { "__umodhi3", "__mspabi_remu" },
1826 { "__umodsi3", "__mspabi_remul" },
1827 { "__umoddi3", "__mspabi_remull" },
1829 /* Bitwise operations. */
1830 /* Rotation - no rotation support yet. */
1831 /* Logical left shift - gcc already does these itself. */
1832 /* Arithmetic left shift - gcc already does these itself. */
1833 /* Arithmetic right shift - gcc already does these itself. */
1835 { NULL, NULL }
1838 /* This function does the same as the default, but it will replace GCC
1839 function names with the MSPABI-specified ones. */
1840 void
1841 msp430_output_labelref (FILE *file, const char *name)
1843 int i;
1845 for (i = 0; helper_function_name_mappings [i].gcc_name; i++)
1846 if (! strcmp (helper_function_name_mappings [i].gcc_name, name))
1848 fputs (helper_function_name_mappings [i].ti_name, file);
1849 return;
1852 fputs (name, file);
1855 /* Common code for msp430_print_operand... */
1857 static void
1858 msp430_print_operand_raw (FILE * file, rtx op)
1860 HOST_WIDE_INT i;
1862 switch (GET_CODE (op))
1864 case REG:
1865 fprintf (file, "%s", reg_names [REGNO (op)]);
1866 break;
1868 case CONST_INT:
1869 i = INTVAL (op);
1870 if (TARGET_ASM_HEX)
1871 fprintf (file, "%#" HOST_WIDE_INT_PRINT "x", i);
1872 else
1873 fprintf (file, "%" HOST_WIDE_INT_PRINT "d", i);
1874 break;
1876 case CONST:
1877 case PLUS:
1878 case MINUS:
1879 case SYMBOL_REF:
1880 case LABEL_REF:
1881 output_addr_const (file, op);
1882 break;
1884 default:
1885 print_rtl (file, op);
1886 break;
1890 #undef TARGET_PRINT_OPERAND_ADDRESS
1891 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
1893 /* Output to stdio stream FILE the assembler syntax for an
1894 instruction operand that is a memory reference whose address
1895 is ADDR. */
1897 static void
1898 msp430_print_operand_addr (FILE * file, rtx addr)
1900 switch (GET_CODE (addr))
1902 case PLUS:
1903 msp430_print_operand_raw (file, XEXP (addr, 1));
1904 gcc_assert (REG_P (XEXP (addr, 0)));
1905 fprintf (file, "(%s)", reg_names [REGNO (XEXP (addr, 0))]);
1906 return;
1908 case REG:
1909 fprintf (file, "@");
1910 break;
1912 case CONST:
1913 case CONST_INT:
1914 case SYMBOL_REF:
1915 case LABEL_REF:
1916 fprintf (file, "&");
1917 break;
1919 default:
1920 break;
1923 msp430_print_operand_raw (file, addr);
1926 #undef TARGET_PRINT_OPERAND
1927 #define TARGET_PRINT_OPERAND msp430_print_operand
1929 /* A low 16-bits of int/lower of register pair
1930 B high 16-bits of int/higher of register pair
1931 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
1932 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
1933 H like %B (for backwards compatibility)
1934 I inverse of value
1935 J an integer without a # prefix
1936 L like %A (for backwards compatibility)
1937 O offset of the top of the stack
1938 Q like X but generates an A postfix
1939 R inverse of condition code, unsigned.
1940 X X instruction postfix in large mode
1941 Y value - 4
1942 Z value - 1
1943 b .B or .W or .A, depending upon the mode
1944 p bit position
1945 r inverse of condition code
1946 x like X but only for pointers. */
1948 static void
1949 msp430_print_operand (FILE * file, rtx op, int letter)
1951 rtx addr;
1953 /* We can't use c, n, a, or l. */
1954 switch (letter)
1956 case 'Z':
1957 gcc_assert (CONST_INT_P (op));
1958 /* Print the constant value, less one. */
1959 fprintf (file, "#%ld", INTVAL (op) - 1);
1960 return;
1961 case 'Y':
1962 gcc_assert (CONST_INT_P (op));
1963 /* Print the constant value, less four. */
1964 fprintf (file, "#%ld", INTVAL (op) - 4);
1965 return;
1966 case 'I':
1967 if (GET_CODE (op) == CONST_INT)
1969 /* Inverse of constants */
1970 int i = INTVAL (op);
1971 fprintf (file, "%d", ~i);
1972 return;
1974 op = XEXP (op, 0);
1975 break;
1976 case 'r': /* Conditional jump where the condition is reversed. */
1977 switch (GET_CODE (op))
1979 case EQ: fprintf (file, "NE"); break;
1980 case NE: fprintf (file, "EQ"); break;
1981 case GEU: fprintf (file, "LO"); break;
1982 case LTU: fprintf (file, "HS"); break;
1983 case GE: fprintf (file, "L"); break;
1984 case LT: fprintf (file, "GE"); break;
1985 /* Assume these have reversed operands. */
1986 case GTU: fprintf (file, "HS"); break;
1987 case LEU: fprintf (file, "LO"); break;
1988 case GT: fprintf (file, "GE"); break;
1989 case LE: fprintf (file, "L"); break;
1990 default:
1991 msp430_print_operand_raw (file, op);
1992 break;
1994 return;
1995 case 'R': /* Conditional jump where the operands are reversed. */
1996 switch (GET_CODE (op))
1998 case GTU: fprintf (file, "LO"); break;
1999 case LEU: fprintf (file, "HS"); break;
2000 case GT: fprintf (file, "L"); break;
2001 case LE: fprintf (file, "GE"); break;
2002 default:
2003 msp430_print_operand_raw (file, op);
2004 break;
2006 return;
2007 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
2008 gcc_assert (CONST_INT_P (op));
2009 fprintf (file, "#%d", 1 << INTVAL (op));
2010 return;
2011 case 'b':
2012 switch (GET_MODE (op))
2014 case QImode: fprintf (file, ".B"); return;
2015 case HImode: fprintf (file, ".W"); return;
2016 case PSImode: fprintf (file, ".A"); return;
2017 case SImode: fprintf (file, ".A"); return;
2018 default:
2019 return;
2021 case 'A':
2022 case 'L': /* Low half. */
2023 switch (GET_CODE (op))
2025 case MEM:
2026 op = adjust_address (op, Pmode, 0);
2027 break;
2028 case REG:
2029 break;
2030 case CONST_INT:
2031 op = GEN_INT (INTVAL (op) & 0xffff);
2032 letter = 0;
2033 break;
2034 default:
2035 /* If you get here, figure out a test case :-) */
2036 gcc_unreachable ();
2038 break;
2039 case 'B':
2040 case 'H': /* high half */
2041 switch (GET_CODE (op))
2043 case MEM:
2044 op = adjust_address (op, Pmode, 2);
2045 break;
2046 case REG:
2047 op = gen_rtx_REG (Pmode, REGNO (op) + 1);
2048 break;
2049 case CONST_INT:
2050 op = GEN_INT (INTVAL (op) >> 16);
2051 letter = 0;
2052 break;
2053 default:
2054 /* If you get here, figure out a test case :-) */
2055 gcc_unreachable ();
2057 break;
2058 case 'C':
2059 switch (GET_CODE (op))
2061 case MEM:
2062 op = adjust_address (op, Pmode, 3);
2063 break;
2064 case REG:
2065 op = gen_rtx_REG (Pmode, REGNO (op) + 2);
2066 break;
2067 case CONST_INT:
2068 op = GEN_INT (INTVAL (op) >> 32);
2069 letter = 0;
2070 break;
2071 default:
2072 /* If you get here, figure out a test case :-) */
2073 gcc_unreachable ();
2075 break;
2076 case 'D':
2077 switch (GET_CODE (op))
2079 case MEM:
2080 op = adjust_address (op, Pmode, 4);
2081 break;
2082 case REG:
2083 op = gen_rtx_REG (Pmode, REGNO (op) + 3);
2084 break;
2085 case CONST_INT:
2086 op = GEN_INT (INTVAL (op) >> 48);
2087 letter = 0;
2088 break;
2089 default:
2090 /* If you get here, figure out a test case :-) */
2091 gcc_unreachable ();
2093 break;
2095 case 'X':
2096 /* This is used to turn, for example, an ADD opcode into an ADDX
2097 opcode when we're using 20-bit addresses. */
2098 if (TARGET_LARGE)
2099 fprintf (file, "X");
2100 /* We don't care which operand we use, but we want 'X' in the MD
2101 file, so we do it this way. */
2102 return;
2104 case 'x':
2105 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
2106 if (TARGET_LARGE && GET_MODE (op) == PSImode)
2107 fprintf (file, "X");
2108 return;
2110 case 'Q':
2111 /* Likewise, for BR -> BRA. */
2112 if (TARGET_LARGE)
2113 fprintf (file, "A");
2114 return;
2116 case 'O':
2117 /* Computes the offset to the top of the stack for the current frame.
2118 This has to be done here rather than in, say, msp430_expand_builtin()
2119 because builtins are expanded before the frame layout is determined. */
2120 fprintf (file, "%d",
2121 msp430_initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM)
2122 - 2);
2123 return;
2125 case 'J':
2126 gcc_assert (GET_CODE (op) == CONST_INT);
2127 case 0:
2128 break;
2129 default:
2130 output_operand_lossage ("invalid operand prefix");
2131 return;
2134 switch (GET_CODE (op))
2136 case REG:
2137 msp430_print_operand_raw (file, op);
2138 break;
2140 case MEM:
2141 addr = XEXP (op, 0);
2142 msp430_print_operand_addr (file, addr);
2143 break;
2145 case CONST_INT:
2146 case CONST:
2147 case SYMBOL_REF:
2148 case LABEL_REF:
2149 if (letter == 0)
2150 fprintf (file, "#");
2151 msp430_print_operand_raw (file, op);
2152 break;
2154 case EQ: fprintf (file, "EQ"); break;
2155 case NE: fprintf (file, "NE"); break;
2156 case GEU: fprintf (file, "HS"); break;
2157 case LTU: fprintf (file, "LO"); break;
2158 case GE: fprintf (file, "GE"); break;
2159 case LT: fprintf (file, "L"); break;
2161 default:
2162 print_rtl (file, op);
2163 break;
2168 /* Frame stuff. */
2171 msp430_return_addr_rtx (int count)
2173 int ra_size;
2174 if (count)
2175 return NULL_RTX;
2177 ra_size = TARGET_LARGE ? 4 : 2;
2178 if (crtl->args.pretend_args_size)
2179 ra_size += 2;
2181 return gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, arg_pointer_rtx, GEN_INT (- ra_size)));
2185 msp430_incoming_return_addr_rtx (void)
2187 return gen_rtx_MEM (Pmode, stack_pointer_rtx);
2190 /* Instruction generation stuff. */
2192 /* Generate a sequence of instructions to sign-extend an HI
2193 value into an SI value. Handles the tricky case where
2194 we are overwriting the destination. */
2196 const char *
2197 msp430x_extendhisi (rtx * operands)
2199 if (REGNO (operands[0]) == REGNO (operands[1]))
2200 /* Low word of dest == source word. */
2201 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
2203 if (! msp430x)
2204 /* Note: This sequence is approximately the same length as invoking a helper
2205 function to perform the sign-extension, as in:
2207 MOV.W %1, %L0
2208 MOV.W %1, r12
2209 CALL __mspabi_srai_15
2210 MOV.W r12, %H0
2212 but this version does not involve any function calls or using argument
2213 registers, so it reduces register pressure. */
2214 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
2216 if (REGNO (operands[0]) + 1 == REGNO (operands[1]))
2217 /* High word of dest == source word. */
2218 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
2220 /* No overlap between dest and source. */
2221 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
2224 /* Likewise for logical right shifts. */
2225 const char *
2226 msp430x_logical_shift_right (rtx amount)
2228 /* The MSP430X's logical right shift instruction - RRUM - does
2229 not use an extension word, so we cannot encode a repeat count.
2230 Try various alternatives to work around this. If the count
2231 is in a register we are stuck, hence the assert. */
2232 gcc_assert (CONST_INT_P (amount));
2234 if (INTVAL (amount) <= 0
2235 || INTVAL (amount) >= 16)
2236 return "# nop logical shift.";
2238 if (INTVAL (amount) > 0
2239 && INTVAL (amount) < 5)
2240 return "rrum.w\t%2, %0"; /* Two bytes. */
2242 if (INTVAL (amount) > 4
2243 && INTVAL (amount) < 9)
2244 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
2246 /* First we logically shift right by one. Now we know
2247 that the top bit is zero and we can use the arithmetic
2248 right shift instruction to perform the rest of the shift. */
2249 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
2252 struct gcc_target targetm = TARGET_INITIALIZER;
2254 #include "gt-msp430.h"