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)
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/>. */
23 #include "coretypes.h"
26 #include "stor-layout.h"
30 #include "hard-reg-set.h"
31 #include "insn-config.h"
32 #include "conditions.h"
34 #include "insn-attr.h"
41 #include "diagnostic-core.h"
49 #include "target-def.h"
50 #include "langhooks.h"
51 #include "msp430-protos.h"
56 static void msp430_compute_frame_info (void);
60 /* Run-time Target Specification. */
64 struct GTY(()) machine_function
66 /* If set, the rest of the fields have been 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... */
73 /* 2/4 bytes for saved PC */
77 int framesize_outgoing
;
81 /* How much we adjust the stack when returning from an exception
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 ();
98 #undef TARGET_HANDLE_OPTION
99 #define TARGET_HANDLE_OPTION msp430_handle_option
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
)
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. */
176 msp430_mcu_name (void)
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
]);
189 return msp430x
? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
193 msp430_option_override (void)
195 init_machine_status
= msp430_init_machine_status
;
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)
204 else if (strcasecmp (target_cpu
, "msp430") == 0
205 || strcasecmp (target_cpu
, "430") == 0)
208 error ("unrecognised argument of -mcpu: %s", target_cpu
);
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
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
224 if (strcasecmp (target_mcu
, "msp430") == 0)
229 else if (strcasecmp (target_mcu
, "msp430x") == 0
230 || strcasecmp (target_mcu
, "msp430xv2") == 0)
233 for (i
= ARRAY_SIZE (msp430_mcu_names
); i
--;)
234 if (strcasecmp (msp430_mcu_names
[i
], target_mcu
) == 0)
239 /* It is not an error if we do not match the MCU name. There are
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;
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)
264 #undef TARGET_MS_BITFIELD_LAYOUT_P
265 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
268 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED
)
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
)
285 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
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. */
299 msp430_modes_tieable_p (enum machine_mode mode1
, enum machine_mode mode2
)
301 if ((mode1
== PSImode
|| mode2
== SImode
)
302 || (mode1
== SImode
|| mode2
== PSImode
))
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
315 msp430_frame_pointer_required (void)
320 #undef TARGET_CAN_ELIMINATE
321 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
324 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED
,
325 const int to_reg ATTRIBUTE_UNUSED
)
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 ();
340 case STACK_POINTER_REGNUM
:
341 rv
+= cfun
->machine
->framesize_outgoing
;
342 rv
+= cfun
->machine
->framesize_locals
;
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. */
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
:
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
)
385 case ADDR_SPACE_GENERIC
:
387 case ADDR_SPACE_NEAR
:
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
409 msp430_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
411 if (subset
== superset
)
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. */
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
));
427 if (to_as
!= ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_FAR
)
429 /* This is unpredictable, as we're truncating off usable address
433 return gen_rtx_CONST (HImode
, op
);
435 result
= gen_reg_rtx (HImode
);
436 emit_insn (gen_truncpsihi2 (result
, op
));
439 else if (to_as
== ADDR_SPACE_FAR
&& from_as
!= ADDR_SPACE_FAR
)
441 /* This always works. */
444 return gen_rtx_CONST (PSImode
, op
);
446 result
= gen_reg_rtx (PSImode
);
447 emit_insn (gen_zero_extendhipsi2 (result
, op
));
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",
468 "__adddf3", "__mspabi_addd",
469 "__subdf3", "__mspabi_subd",
470 "__muldf3", "__mspabi_mpyd",
471 "__divdf3", "__mspabi_divd",
476 /* TRUE if the function passed is a "speical" function. Special
477 functions pass two DImode parameters in registers. */
479 msp430_special_register_convention_p (const char *name
)
483 for (i
= 0; special_convention_function_names
[i
]; i
++)
484 if (! strcmp (name
, special_convention_function_names
[i
]))
490 #undef TARGET_FUNCTION_VALUE_REGNO_P
491 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
494 msp430_function_value_regno_p (unsigned int regno
)
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. */
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
)
529 memset (ca
, 0, sizeof(*ca
));
534 fname
= IDENTIFIER_POINTER (DECL_NAME (fndecl
));
536 fname
= XSTR (libname
, 0);
540 if (fname
&& msp430_special_register_convention_p (fname
))
544 /* Helper function for argument passing; this function is the common
545 code that determines where an argument will be passed. */
547 msp430_evaluate_arg (cumulative_args_t cap
,
548 enum machine_mode mode
,
549 const_tree type ATTRIBUTE_UNUSED
,
552 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
553 int nregs
= GET_MODE_SIZE (mode
);
565 nregs
= (nregs
+ 1) / 2;
569 /* Function is passed two DImode operands, in R8:R11 and
579 for (i
= 0; i
< 4; i
++)
580 if (! ca
->reg_used
[i
])
583 ca
->start_reg
= CA_FIRST_REG
+ i
;
588 for (i
= 0; i
< 3; i
++)
589 if (! ca
->reg_used
[i
] && ! ca
->reg_used
[i
+ 1])
592 ca
->start_reg
= CA_FIRST_REG
+ i
;
595 if (! ca
->reg_used
[3] && ca
->can_split
)
599 ca
->start_reg
= CA_FIRST_REG
+ 3;
606 if (! ca
->reg_used
[0]
607 && ! ca
->reg_used
[1]
608 && ! ca
->reg_used
[2]
609 && ! ca
->reg_used
[3])
612 ca
->start_reg
= CA_FIRST_REG
;
619 #undef TARGET_PROMOTE_PROTOTYPES
620 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
623 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED
)
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
,
637 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
639 msp430_evaluate_arg (cap
, mode
, type
, named
);
642 return gen_rtx_REG (mode
, ca
->start_reg
);
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
,
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
;
666 #undef TARGET_PASS_BY_REFERENCE
667 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
670 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED
,
671 enum machine_mode mode
,
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
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
)
692 #undef TARGET_FUNCTION_ARG_ADVANCE
693 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
696 msp430_function_arg_advance (cumulative_args_t cap
,
697 enum machine_mode mode
,
701 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
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;
713 #undef TARGET_FUNCTION_ARG_BOUNDARY
714 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
717 msp430_function_arg_boundary (enum machine_mode mode
, const_tree type
)
720 && int_size_in_bytes (type
) > 1)
722 if (GET_MODE_BITSIZE (mode
) > 8)
727 #undef TARGET_RETURN_IN_MEMORY
728 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
731 msp430_return_in_memory (const_tree ret_type
, const_tree fntype ATTRIBUTE_UNUSED
)
733 enum machine_mode mode
= TYPE_MODE (ret_type
);
736 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == RECORD_TYPE
)
737 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == UNION_TYPE
))
740 if (GET_MODE_SIZE (mode
) > 8)
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
)
764 /* Addressing Modes */
766 #undef TARGET_LEGITIMATE_ADDRESS_P
767 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
770 reg_ok_for_addr (rtx r
, bool strict
)
774 if (strict
&& rn
>= FIRST_PSEUDO_REGISTER
)
775 rn
= reg_renumber
[rn
];
776 if (strict
&& 0 <= rn
&& rn
< FIRST_PSEUDO_REGISTER
)
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
))
794 if (REG_P (XEXP (x
, 0)))
796 if (GET_MODE (x
) != GET_MODE (XEXP (x
, 0)))
798 if (!reg_ok_for_addr (XEXP (x
, 0), strict
))
800 switch (GET_CODE (XEXP (x
, 1)))
813 if (!reg_ok_for_addr (x
, strict
))
826 #undef TARGET_LEGITIMATE_CONSTANT_P
827 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
830 msp430_legitimate_constant (enum machine_mode mode
, rtx x
)
832 return ! CONST_INT_P (x
)
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
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
,
846 int outer_code ATTRIBUTE_UNUSED
,
847 int opno ATTRIBUTE_UNUSED
,
849 bool speed ATTRIBUTE_UNUSED
)
854 if (GET_MODE (x
) == SImode
&& outer_code
== SET
)
856 *total
= COSTS_N_INSNS (4);
865 *total
= COSTS_N_INSNS (100);
873 /* Function Entry and Exit */
875 /* The MSP430 call frame looks like this:
878 +--------------------+
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 |
890 +--------------------+ <-- SP before prologue, also AP
892 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
894 +--------------------+ <-- "frame pointer"
898 +--------------------+
902 +--------------------+ <-- SP during function
907 /* We use this to wrap all emitted insns in the prologue, so they get
908 the "frame-related" (/f) flag set. */
912 RTX_FRAME_RELATED_P (x
) = 1;
916 /* This is the one spot that decides if a register is to be saved and
917 restored in the prologue/epilogue. */
919 msp430_preserve_reg_p (int regno
)
921 /* PC, SP, SR, and the constant generator. */
925 /* FIXME: add interrupt, EH, etc. */
926 if (crtl
->calls_eh_return
)
929 /* Shouldn't be more than the above, but just in case... */
930 if (fixed_regs
[regno
])
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
))
946 /* Compute all the frame-related fields in our machine_function
949 msp430_compute_frame_info (void)
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);
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
);
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. */
984 msp430_is_interrupt_func (void)
986 if (current_function_decl
== NULL
)
988 return is_attr_func ("interrupt");
992 is_wakeup_func (void)
994 return msp430_is_interrupt_func () && is_attr_func ("wakeup");
1000 return is_attr_func ("naked");
1004 is_reentrant_func (void)
1006 return is_attr_func ("reentrant");
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
1019 msp430_start_function (FILE *outfile
, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED
)
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
));
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
]);
1057 fprintf (outfile
, "(none)");
1058 fprintf (outfile
, "\n");
1061 /* Common code to change the stack pointer. */
1063 increment_stack (HOST_WIDE_INT amount
)
1066 rtx sp
= stack_pointer_rtx
;
1073 inc
= GEN_INT (- amount
);
1075 F (emit_insn (gen_subpsi3 (sp
, sp
, inc
)));
1077 F (emit_insn (gen_subhi3 (sp
, sp
, inc
)));
1081 inc
= GEN_INT (amount
);
1083 emit_insn (gen_addpsi3 (sp
, sp
, inc
));
1085 emit_insn (gen_addhi3 (sp
, sp
, inc
));
1089 /* Verify MSP430 specific attributes. */
1092 msp430_attr (tree
* node
,
1095 int flags ATTRIBUTE_UNUSED
,
1096 bool * no_add_attrs
)
1098 gcc_assert (DECL_P (* node
));
1102 tree value
= TREE_VALUE (args
);
1104 switch (TREE_CODE (value
))
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",
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",
1127 warning (OPT_Wattributes
,
1128 "argument of %qE attribute is not a string constant or number",
1130 *no_add_attrs
= true;
1135 if (TREE_CODE (* node
) != FUNCTION_DECL
)
1137 warning (OPT_Wattributes
,
1138 "%qE attribute only applies to functions",
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. */
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 }
1169 msp430_start_function (FILE *file
, const char *name
, tree decl
)
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
)
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
);
1203 switch_to_section (function_section (decl
));
1204 ASM_OUTPUT_FUNCTION_LABEL (file
, name
, decl
);
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. */
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
1225 MSP430_BUILTIN_BIC_SR
,
1226 MSP430_BUILTIN_BIS_SR
,
1230 static GTY(()) tree msp430_builtins
[(int) MSP430_BUILTIN_max
];
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
);
1247 msp430_builtin_decl (unsigned code
, bool initialize ATTRIBUTE_UNUSED
)
1251 case MSP430_BUILTIN_BIC_SR
:
1252 case MSP430_BUILTIN_BIS_SR
:
1253 return msp430_builtins
[code
];
1255 return error_mark_node
;
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");
1276 if (! REG_P (arg1
) && ! CONSTANT_P (arg1
))
1277 arg1
= force_reg (mode
, arg1
);
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;
1284 internal_error ("bad builtin code");
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
1300 msp430_expand_prologue (void)
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
;
1311 if (is_naked_func ())
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
)
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))),
1347 add_reg_note (p
, REG_CFA_OFFSET
, note
);
1351 for (i
= 15; i
>= 4; i
--)
1352 if (cfun
->machine
->need_to_save
[i
])
1357 for (seq
= i
- 1; seq
>= 4 && cfun
->machine
->need_to_save
[seq
]; seq
--)
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
),
1367 note
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (count
+ 1));
1369 XVECEXP (note
, 0, 0)
1370 = F (gen_rtx_SET (VOIDmode
,
1372 gen_rtx_PLUS (Pmode
,
1374 GEN_INT (count
* (TARGET_LARGE
? -4 : -2)))));
1376 /* *sp-- = R[i-j] */
1380 for (j
= 0; j
< count
; j
++)
1383 int ofs
= (count
- j
- 1) * (TARGET_LARGE
? 4 : 2);
1386 addr
= gen_rtx_PLUS (Pmode
, sp
, GEN_INT (ofs
));
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
);
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 ());
1414 msp430_expand_epilogue (int is_eh
)
1420 if (is_naked_func ())
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
])
1432 if (cfun
->machine
->need_to_save
[i
])
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
);
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
])
1480 for (seq
= i
+ 1; seq
<= 15 && cfun
->machine
->need_to_save
[seq
]; seq
++)
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),
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. */
1501 emit_insn (gen_epilogue_helper (GEN_INT (helper_n
)));
1505 emit_insn (gen_pop (gen_rtx_REG (Pmode
, i
)));
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
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
)
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. */
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 ();
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. */
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
),
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
1592 msp430_expand_helper (rtx
*operands
, const char *helper_name
, bool const_variants
)
1595 char *helper_const
= NULL
;
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]))
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]));
1619 if (arg1mode
== VOIDmode
)
1620 arg1mode
= arg0mode
;
1621 if (arg2mode
== VOIDmode
)
1622 arg2mode
= arg0mode
;
1624 if (arg1mode
== SImode
)
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),
1644 emit_move_insn (gen_rtx_REG (arg2mode
, arg2
),
1647 c
= gen_call_value_internal (gen_rtx_REG (arg0mode
, 12),
1648 gen_rtx_SYMBOL_REF (VOIDmode
, helper_const
? helper_const
: helper_name
),
1650 c
= emit_call_insn (c
);
1651 RTL_CONST_CALL_P (c
) = 1;
1654 use_regs (&f
, 12, arg1sz
);
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. */
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
))
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
)
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
1696 rv
= gen_rtx_SUBREG (mode
, ireg
, byte
);
1698 rv
= simplify_gen_subreg (mode
, ireg
, imode
, byte
);
1700 else if (GET_CODE (r
) == MEM
)
1701 rv
= adjust_address (r
, mode
, byte
);
1703 rv
= simplify_gen_subreg (mode
, r
, omode
, byte
);
1711 /* Called by movsi_x to generate the HImode operands. */
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
);
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]))
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
))
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. */
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" },
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?) */
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. */
1848 /* Returns true if the current MCU is an F5xxx series. */
1850 msp430_is_f5_mcu (void)
1852 if (target_mcu
== NULL
)
1854 return strncasecmp (target_mcu
, "msp430f5", 8) == 0;
1857 /* Returns true id the current MCU has a second generation 32-bit hardware multiplier. */
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"
1871 if (target_mcu
== NULL
)
1874 for (i
= ARRAY_SIZE (known_32bit_mult_mcus
); i
--;)
1875 if (strcasecmp (target_mcu
, known_32bit_mult_mcus
[i
]) == 0)
1881 /* Returns true if hardware multiply is supported by the chosen MCU. */
1883 msp430_hwmult_enabled (void)
1885 if (target_mcu
== NULL
)
1891 if (msp430_is_interrupt_func ())
1894 if (msp430_is_f5_mcu () || has_32bit_hw_mult ())
1900 /* This function does the same as the default, but it will replace GCC
1901 function names with the MSPABI-specified ones. */
1903 msp430_output_labelref (FILE *file
, const char *name
)
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
;
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";
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";
1939 /* Common code for msp430_print_operand... */
1942 msp430_print_operand_raw (FILE * file
, rtx op
)
1946 switch (GET_CODE (op
))
1949 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
1955 fprintf (file
, "%#" HOST_WIDE_INT_PRINT
"x", i
);
1957 fprintf (file
, "%" HOST_WIDE_INT_PRINT
"d", i
);
1965 output_addr_const (file
, op
);
1969 print_rtl (file
, op
);
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
1982 msp430_print_operand_addr (FILE * file
, rtx addr
)
1984 switch (GET_CODE (addr
))
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))]);
1993 fprintf (file
, "@");
2000 fprintf (file
, "&");
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)
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
2027 b .B or .W or .A, depending upon the mode
2029 r inverse of condition code
2030 x like X but only for pointers. */
2033 msp430_print_operand (FILE * file
, rtx op
, int letter
)
2037 /* We can't use c, n, a, or l. */
2041 gcc_assert (CONST_INT_P (op
));
2042 /* Print the constant value, less one. */
2043 fprintf (file
, "#%ld", INTVAL (op
) - 1);
2046 gcc_assert (CONST_INT_P (op
));
2047 /* Print the constant value, less four. */
2048 fprintf (file
, "#%ld", INTVAL (op
) - 4);
2051 if (GET_CODE (op
) == CONST_INT
)
2053 /* Inverse of constants */
2054 int i
= INTVAL (op
);
2055 fprintf (file
, "%d", ~i
);
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;
2075 msp430_print_operand_raw (file
, op
);
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;
2087 msp430_print_operand_raw (file
, op
);
2091 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
2092 gcc_assert (CONST_INT_P (op
));
2093 fprintf (file
, "#%d", 1 << INTVAL (op
));
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;
2106 case 'L': /* Low half. */
2107 switch (GET_CODE (op
))
2110 op
= adjust_address (op
, Pmode
, 0);
2115 op
= GEN_INT (INTVAL (op
) & 0xffff);
2119 /* If you get here, figure out a test case :-) */
2124 case 'H': /* high half */
2125 switch (GET_CODE (op
))
2128 op
= adjust_address (op
, Pmode
, 2);
2131 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 1);
2134 op
= GEN_INT (INTVAL (op
) >> 16);
2138 /* If you get here, figure out a test case :-) */
2143 switch (GET_CODE (op
))
2146 op
= adjust_address (op
, Pmode
, 3);
2149 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 2);
2152 op
= GEN_INT ((long long) INTVAL (op
) >> 32);
2156 /* If you get here, figure out a test case :-) */
2161 switch (GET_CODE (op
))
2164 op
= adjust_address (op
, Pmode
, 4);
2167 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 3);
2170 op
= GEN_INT ((long long) INTVAL (op
) >> 48);
2174 /* If you get here, figure out a test case :-) */
2180 /* This is used to turn, for example, an ADD opcode into an ADDX
2181 opcode when we're using 20-bit addresses. */
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. */
2189 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
2190 if (TARGET_LARGE
&& GET_MODE (op
) == PSImode
)
2191 fprintf (file
, "X");
2195 /* Likewise, for BR -> BRA. */
2197 fprintf (file
, "A");
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
)
2210 gcc_assert (GET_CODE (op
) == CONST_INT
);
2214 output_operand_lossage ("invalid operand prefix");
2218 switch (GET_CODE (op
))
2221 msp430_print_operand_raw (file
, op
);
2225 addr
= XEXP (op
, 0);
2226 msp430_print_operand_addr (file
, addr
);
2234 fprintf (file
, "#");
2235 msp430_print_operand_raw (file
, op
);
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;
2246 print_rtl (file
, op
);
2255 msp430_return_addr_rtx (int count
)
2261 ra_size
= TARGET_LARGE
? 4 : 2;
2262 if (crtl
->args
.pretend_args_size
)
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. */
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. */
2288 /* Note: This sequence is approximately the same length as invoking a helper
2289 function to perform the sign-extension, as in:
2293 CALL __mspabi_srai_15
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. */
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"