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_OPTION_OVERRIDE
99 #define TARGET_OPTION_OVERRIDE msp430_option_override
101 static const char * msp430_mcu_names
[] =
103 "msp430afe221", "msp430afe222", "msp430afe223", "msp430afe231",
104 "msp430afe232", "msp430afe233", "msp430afe251", "msp430afe252",
105 "msp430afe253", "msp430c091", "msp430c092", "msp430c111",
106 "msp430c1111", "msp430c112", "msp430c1121", "msp430c1331",
107 "msp430c1351", "msp430c311s", "msp430c312", "msp430c313",
108 "msp430c314", "msp430c315", "msp430c323", "msp430c325",
109 "msp430c336", "msp430c337", "msp430c412", "msp430c413",
110 "msp430e112", "msp430e313", "msp430e315", "msp430e325",
111 "msp430e337", "msp430f110", "msp430f1101", "msp430f1101a",
112 "msp430f1111", "msp430f1111a", "msp430f112", "msp430f1121",
113 "msp430f1121a", "msp430f1122", "msp430f1132", "msp430f122",
114 "msp430f1222", "msp430f123", "msp430f1232", "msp430f133",
115 "msp430f135", "msp430f147", "msp430f1471", "msp430f148",
116 "msp430f1481", "msp430f149", "msp430f1491", "msp430f155",
117 "msp430f156", "msp430f157", "msp430f1610", "msp430f1611",
118 "msp430f1612", "msp430f167", "msp430f168", "msp430f169",
119 "msp430f2001", "msp430f2002", "msp430f2003", "msp430f2011",
120 "msp430f2012", "msp430f2013", "msp430f2101", "msp430f2111",
121 "msp430f2112", "msp430f2121", "msp430f2122", "msp430f2131",
122 "msp430f2132", "msp430f2232", "msp430f2234", "msp430f2252",
123 "msp430f2254", "msp430f2272", "msp430f2274", "msp430f233",
124 "msp430f2330", "msp430f235", "msp430f2350", "msp430f2370",
125 "msp430f2410", "msp430f247", "msp430f2471", "msp430f248",
126 "msp430f2481", "msp430f249", "msp430f2491", "msp430f412",
127 "msp430f413", "msp430f4132", "msp430f415", "msp430f4152",
128 "msp430f417", "msp430f423", "msp430f423a", "msp430f425",
129 "msp430f4250", "msp430f425a", "msp430f4260", "msp430f427",
130 "msp430f4270", "msp430f427a", "msp430f435", "msp430f4351",
131 "msp430f436", "msp430f4361", "msp430f437", "msp430f4371",
132 "msp430f438", "msp430f439", "msp430f447", "msp430f448",
133 "msp430f4481", "msp430f449", "msp430f4491", "msp430f477",
134 "msp430f478", "msp430f4783", "msp430f4784", "msp430f479",
135 "msp430f4793", "msp430f4794", "msp430fe423", "msp430fe4232",
136 "msp430fe423a", "msp430fe4242", "msp430fe425", "msp430fe4252",
137 "msp430fe425a", "msp430fe427", "msp430fe4272", "msp430fe427a",
138 "msp430fg4250", "msp430fg4260", "msp430fg4270", "msp430fg437",
139 "msp430fg438", "msp430fg439", "msp430fg477", "msp430fg478",
140 "msp430fg479", "msp430fw423", "msp430fw425", "msp430fw427",
141 "msp430fw428", "msp430fw429", "msp430g2001", "msp430g2101",
142 "msp430g2102", "msp430g2111", "msp430g2112", "msp430g2113",
143 "msp430g2121", "msp430g2131", "msp430g2132", "msp430g2152",
144 "msp430g2153", "msp430g2201", "msp430g2202", "msp430g2203",
145 "msp430g2210", "msp430g2211", "msp430g2212", "msp430g2213",
146 "msp430g2221", "msp430g2230", "msp430g2231", "msp430g2232",
147 "msp430g2233", "msp430g2252", "msp430g2253", "msp430g2302",
148 "msp430g2303", "msp430g2312", "msp430g2313", "msp430g2332",
149 "msp430g2333", "msp430g2352", "msp430g2353", "msp430g2402",
150 "msp430g2403", "msp430g2412", "msp430g2413", "msp430g2432",
151 "msp430g2433", "msp430g2444", "msp430g2452", "msp430g2453",
152 "msp430g2513", "msp430g2533", "msp430g2544", "msp430g2553",
153 "msp430g2744", "msp430g2755", "msp430g2855", "msp430g2955",
154 "msp430i2020", "msp430i2021", "msp430i2030", "msp430i2031",
155 "msp430i2040", "msp430i2041", "msp430l092", "msp430p112",
156 "msp430p313", "msp430p315", "msp430p315s", "msp430p325",
157 "msp430p337", "msp430tch5e"
160 /* Generate a C preprocessor symbol based upon the MCU selected by the user.
161 If a specific MCU has not been selected then return a generic symbol instead. */
164 msp430_mcu_name (void)
169 static char mcu_name
[64];
171 snprintf (mcu_name
, sizeof (mcu_name
) - 1, "__%s__", target_mcu
);
172 for (i
= strlen (mcu_name
); i
--;)
173 mcu_name
[i
] = TOUPPER (mcu_name
[i
]);
177 return msp430x
? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
181 msp430_option_override (void)
183 init_machine_status
= msp430_init_machine_status
;
187 if (strcasecmp (target_cpu
, "msp430x") == 0)
189 else /* target_cpu == "msp430" - already handled by the front end. */
192 /* Note - the front end has already ensured at most
193 one of target_cpu and target_mcu will be set. */
198 /* If we are given an MCU name, we assume that it supports 430X.
199 Then we check to see if it is one of the known MCUs that only
203 for (i
= ARRAY_SIZE (msp430_mcu_names
); i
--;)
204 if (strcasecmp (msp430_mcu_names
[i
], target_mcu
) == 0)
209 /* It is not an error if we do not match the MCU name. There are
213 if (TARGET_LARGE
&& !msp430x
)
214 error ("-mlarge requires a 430X-compatible -mmcu=");
216 if (flag_exceptions
|| flag_non_call_exceptions
217 || flag_unwind_tables
|| flag_asynchronous_unwind_tables
)
218 flag_omit_frame_pointer
= false;
220 flag_omit_frame_pointer
= true;
222 /* This is a hack to work around a problem with the newlib build
223 mechanism. Newlib always appends CFLAGS to the end of the GCC
224 command line and always sets -O2 in CFLAGS. Thus it is not
225 possible to build newlib with -Os enabled. Until now... */
226 if (TARGET_OPT_SPACE
&& optimize
< 3)
234 #undef TARGET_MS_BITFIELD_LAYOUT_P
235 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
238 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED
)
247 /* Implements HARD_REGNO_NREGS. MSP430X registers can hold a single
248 PSImode value, but not an SImode value. */
250 msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED
,
251 enum machine_mode mode
)
253 if (mode
== PSImode
&& msp430x
)
255 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
259 /* Implements HARD_REGNO_MODE_OK. */
261 msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED
,
262 enum machine_mode mode
)
264 return regno
<= (ARG_POINTER_REGNUM
- msp430_hard_regno_nregs (regno
, mode
));
267 /* Implements MODES_TIEABLE_P. */
269 msp430_modes_tieable_p (enum machine_mode mode1
, enum machine_mode mode2
)
271 if ((mode1
== PSImode
|| mode2
== SImode
)
272 || (mode1
== SImode
|| mode2
== PSImode
))
275 return ((GET_MODE_CLASS (mode1
) == MODE_FLOAT
276 || GET_MODE_CLASS (mode1
) == MODE_COMPLEX_FLOAT
)
277 == (GET_MODE_CLASS (mode2
) == MODE_FLOAT
278 || GET_MODE_CLASS (mode2
) == MODE_COMPLEX_FLOAT
));
281 #undef TARGET_FRAME_POINTER_REQUIRED
282 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
285 msp430_frame_pointer_required (void)
290 #undef TARGET_CAN_ELIMINATE
291 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
294 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED
,
295 const int to_reg ATTRIBUTE_UNUSED
)
300 /* Implements INITIAL_ELIMINATION_OFFSET. */
302 msp430_initial_elimination_offset (int from
, int to
)
304 int rv
= 0; /* As if arg to arg. */
306 msp430_compute_frame_info ();
310 case STACK_POINTER_REGNUM
:
311 rv
+= cfun
->machine
->framesize_outgoing
;
312 rv
+= cfun
->machine
->framesize_locals
;
314 case FRAME_POINTER_REGNUM
:
315 rv
+= cfun
->machine
->framesize_regs
;
316 /* Allow for the saved return address. */
317 rv
+= (TARGET_LARGE
? 4 : 2);
318 /* NB/ No need to allow for crtl->args.pretend_args_size.
319 GCC does that for us. */
327 case FRAME_POINTER_REGNUM
:
328 /* Allow for the fall through above. */
329 rv
-= (TARGET_LARGE
? 4 : 2);
330 rv
-= cfun
->machine
->framesize_regs
;
331 case ARG_POINTER_REGNUM
:
340 /* Named Address Space support */
343 /* Return the appropriate mode for a named address pointer. */
344 #undef TARGET_ADDR_SPACE_POINTER_MODE
345 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
346 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
347 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
349 static enum machine_mode
350 msp430_addr_space_pointer_mode (addr_space_t addrspace
)
355 case ADDR_SPACE_GENERIC
:
357 case ADDR_SPACE_NEAR
:
364 /* Function pointers are stored in unwind_word sized
365 variables, so make sure that unwind_word is big enough. */
366 #undef TARGET_UNWIND_WORD_MODE
367 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
369 static enum machine_mode
370 msp430_unwind_word_mode (void)
372 return TARGET_LARGE
? SImode
: HImode
;
375 /* Determine if one named address space is a subset of another. */
376 #undef TARGET_ADDR_SPACE_SUBSET_P
377 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
379 msp430_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
381 if (subset
== superset
)
384 return (subset
!= ADDR_SPACE_FAR
&& superset
== ADDR_SPACE_FAR
);
387 #undef TARGET_ADDR_SPACE_CONVERT
388 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
389 /* Convert from one address space to another. */
391 msp430_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
393 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
394 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
397 if (to_as
!= ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_FAR
)
399 /* This is unpredictable, as we're truncating off usable address
403 return gen_rtx_CONST (HImode
, op
);
405 result
= gen_reg_rtx (HImode
);
406 emit_insn (gen_truncpsihi2 (result
, op
));
409 else if (to_as
== ADDR_SPACE_FAR
&& from_as
!= ADDR_SPACE_FAR
)
411 /* This always works. */
414 return gen_rtx_CONST (PSImode
, op
);
416 result
= gen_reg_rtx (PSImode
);
417 emit_insn (gen_zero_extendhipsi2 (result
, op
));
424 /* Stack Layout and Calling Conventions. */
426 /* For each function, we list the gcc version and the TI version on
427 each line, where we're converting the function names. */
428 static char const * const special_convention_function_names
[] =
430 "__muldi3", "__mspabi_mpyll",
431 "__udivdi3", "__mspabi_divull",
432 "__umoddi3", "__mspabi_remull",
433 "__divdi3", "__mspabi_divlli",
434 "__moddi3", "__mspabi_remlli",
438 "__adddf3", "__mspabi_addd",
439 "__subdf3", "__mspabi_subd",
440 "__muldf3", "__mspabi_mpyd",
441 "__divdf3", "__mspabi_divd",
446 /* TRUE if the function passed is a "speical" function. Special
447 functions pass two DImode parameters in registers. */
449 msp430_special_register_convention_p (const char *name
)
453 for (i
= 0; special_convention_function_names
[i
]; i
++)
454 if (! strcmp (name
, special_convention_function_names
[i
]))
460 #undef TARGET_FUNCTION_VALUE_REGNO_P
461 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
464 msp430_function_value_regno_p (unsigned int regno
)
470 #undef TARGET_FUNCTION_VALUE
471 #define TARGET_FUNCTION_VALUE msp430_function_value
474 msp430_function_value (const_tree ret_type
,
475 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
476 bool outgoing ATTRIBUTE_UNUSED
)
478 return gen_rtx_REG (TYPE_MODE (ret_type
), 12);
481 #undef TARGET_LIBCALL_VALUE
482 #define TARGET_LIBCALL_VALUE msp430_libcall_value
485 msp430_libcall_value (enum machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
487 return gen_rtx_REG (mode
, 12);
490 /* Implements INIT_CUMULATIVE_ARGS. */
492 msp430_init_cumulative_args (CUMULATIVE_ARGS
*ca
,
493 tree fntype ATTRIBUTE_UNUSED
,
494 rtx libname ATTRIBUTE_UNUSED
,
495 tree fndecl ATTRIBUTE_UNUSED
,
496 int n_named_args ATTRIBUTE_UNUSED
)
499 memset (ca
, 0, sizeof(*ca
));
504 fname
= IDENTIFIER_POINTER (DECL_NAME (fndecl
));
506 fname
= XSTR (libname
, 0);
510 if (fname
&& msp430_special_register_convention_p (fname
))
514 /* Helper function for argument passing; this function is the common
515 code that determines where an argument will be passed. */
517 msp430_evaluate_arg (cumulative_args_t cap
,
518 enum machine_mode mode
,
519 const_tree type ATTRIBUTE_UNUSED
,
522 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
523 int nregs
= GET_MODE_SIZE (mode
);
535 nregs
= (nregs
+ 1) / 2;
539 /* Function is passed two DImode operands, in R8:R11 and
549 for (i
= 0; i
< 4; i
++)
550 if (! ca
->reg_used
[i
])
553 ca
->start_reg
= CA_FIRST_REG
+ i
;
558 for (i
= 0; i
< 3; i
++)
559 if (! ca
->reg_used
[i
] && ! ca
->reg_used
[i
+ 1])
562 ca
->start_reg
= CA_FIRST_REG
+ i
;
565 if (! ca
->reg_used
[3] && ca
->can_split
)
569 ca
->start_reg
= CA_FIRST_REG
+ 3;
576 if (! ca
->reg_used
[0]
577 && ! ca
->reg_used
[1]
578 && ! ca
->reg_used
[2]
579 && ! ca
->reg_used
[3])
582 ca
->start_reg
= CA_FIRST_REG
;
589 #undef TARGET_PROMOTE_PROTOTYPES
590 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
593 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED
)
598 #undef TARGET_FUNCTION_ARG
599 #define TARGET_FUNCTION_ARG msp430_function_arg
602 msp430_function_arg (cumulative_args_t cap
,
603 enum machine_mode mode
,
607 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
609 msp430_evaluate_arg (cap
, mode
, type
, named
);
612 return gen_rtx_REG (mode
, ca
->start_reg
);
617 #undef TARGET_ARG_PARTIAL_BYTES
618 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
621 msp430_arg_partial_bytes (cumulative_args_t cap
,
622 enum machine_mode mode
,
626 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
628 msp430_evaluate_arg (cap
, mode
, type
, named
);
630 if (ca
->reg_count
&& ca
->mem_count
)
631 return ca
->reg_count
* UNITS_PER_WORD
;
636 #undef TARGET_PASS_BY_REFERENCE
637 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
640 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED
,
641 enum machine_mode mode
,
643 bool named ATTRIBUTE_UNUSED
)
645 return (mode
== BLKmode
646 || (type
&& TREE_CODE (type
) == RECORD_TYPE
)
647 || (type
&& TREE_CODE (type
) == UNION_TYPE
));
650 #undef TARGET_CALLEE_COPIES
651 #define TARGET_CALLEE_COPIES msp430_callee_copies
654 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED
,
655 enum machine_mode mode ATTRIBUTE_UNUSED
,
656 const_tree type ATTRIBUTE_UNUSED
,
657 bool named ATTRIBUTE_UNUSED
)
662 #undef TARGET_FUNCTION_ARG_ADVANCE
663 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
666 msp430_function_arg_advance (cumulative_args_t cap
,
667 enum machine_mode mode
,
671 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
674 msp430_evaluate_arg (cap
, mode
, type
, named
);
676 if (ca
->start_reg
>= CA_FIRST_REG
)
677 for (i
= 0; i
< ca
->reg_count
; i
++)
678 ca
->reg_used
[i
+ ca
->start_reg
- CA_FIRST_REG
] = 1;
683 #undef TARGET_FUNCTION_ARG_BOUNDARY
684 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
687 msp430_function_arg_boundary (enum machine_mode mode
, const_tree type
)
690 && int_size_in_bytes (type
) > 1)
692 if (GET_MODE_BITSIZE (mode
) > 8)
697 #undef TARGET_RETURN_IN_MEMORY
698 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
701 msp430_return_in_memory (const_tree ret_type
, const_tree fntype ATTRIBUTE_UNUSED
)
703 enum machine_mode mode
= TYPE_MODE (ret_type
);
706 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == RECORD_TYPE
)
707 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == UNION_TYPE
))
710 if (GET_MODE_SIZE (mode
) > 8)
716 #undef TARGET_GET_RAW_ARG_MODE
717 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
719 static enum machine_mode
720 msp430_get_raw_arg_mode (int regno
)
722 return (regno
== ARG_POINTER_REGNUM
) ? VOIDmode
: Pmode
;
725 #undef TARGET_GET_RAW_RESULT_MODE
726 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
728 static enum machine_mode
729 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED
)
734 /* Addressing Modes */
736 #undef TARGET_LEGITIMATE_ADDRESS_P
737 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
740 reg_ok_for_addr (rtx r
, bool strict
)
744 if (strict
&& rn
>= FIRST_PSEUDO_REGISTER
)
745 rn
= reg_renumber
[rn
];
746 if (strict
&& 0 <= rn
&& rn
< FIRST_PSEUDO_REGISTER
)
754 msp430_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED
,
755 rtx x ATTRIBUTE_UNUSED
,
756 bool strict ATTRIBUTE_UNUSED
)
758 switch (GET_CODE (x
))
764 if (REG_P (XEXP (x
, 0)))
766 if (GET_MODE (x
) != GET_MODE (XEXP (x
, 0)))
768 if (!reg_ok_for_addr (XEXP (x
, 0), strict
))
770 switch (GET_CODE (XEXP (x
, 1)))
783 if (!reg_ok_for_addr (x
, strict
))
796 #undef TARGET_LEGITIMATE_CONSTANT_P
797 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
800 msp430_legitimate_constant (enum machine_mode mode
, rtx x
)
802 return ! CONST_INT_P (x
)
804 /* GCC does not know the width of the PSImode, so make
805 sure that it does not try to use a constant value that
807 || (INTVAL (x
) < (1 << 20) && INTVAL (x
) >= (-1 << 20));
811 #undef TARGET_RTX_COSTS
812 #define TARGET_RTX_COSTS msp430_rtx_costs
814 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED
,
816 int outer_code ATTRIBUTE_UNUSED
,
817 int opno ATTRIBUTE_UNUSED
,
819 bool speed ATTRIBUTE_UNUSED
)
824 if (GET_MODE (x
) == SImode
&& outer_code
== SET
)
826 *total
= COSTS_N_INSNS (4);
835 *total
= COSTS_N_INSNS (100);
843 /* Function Entry and Exit */
845 /* The MSP430 call frame looks like this:
848 +--------------------+
852 +--------------------+ <-- "arg pointer"
854 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
856 +--------------------+
857 | SR if this func has|
858 | been called via an |
860 +--------------------+ <-- SP before prologue, also AP
862 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
864 +--------------------+ <-- "frame pointer"
868 +--------------------+
872 +--------------------+ <-- SP during function
877 /* We use this to wrap all emitted insns in the prologue, so they get
878 the "frame-related" (/f) flag set. */
882 RTX_FRAME_RELATED_P (x
) = 1;
886 /* This is the one spot that decides if a register is to be saved and
887 restored in the prologue/epilogue. */
889 msp430_preserve_reg_p (int regno
)
891 /* PC, SP, SR, and the constant generator. */
895 /* FIXME: add interrupt, EH, etc. */
896 if (crtl
->calls_eh_return
)
899 /* Shouldn't be more than the above, but just in case... */
900 if (fixed_regs
[regno
])
903 /* Interrupt handlers save all registers they use, even
904 ones which are call saved. If they call other functions
905 then *every* register is saved. */
906 if (msp430_is_interrupt_func ())
907 return ! crtl
->is_leaf
|| df_regs_ever_live_p (regno
);
909 if (!call_used_regs
[regno
]
910 && df_regs_ever_live_p (regno
))
916 /* Compute all the frame-related fields in our machine_function
919 msp430_compute_frame_info (void)
923 cfun
->machine
->computed
= 1;
924 cfun
->machine
->framesize_regs
= 0;
925 cfun
->machine
->framesize_locals
= get_frame_size ();
926 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
928 for (i
= 0; i
< ARG_POINTER_REGNUM
; i
++)
929 if (msp430_preserve_reg_p (i
))
931 cfun
->machine
->need_to_save
[i
] = 1;
932 cfun
->machine
->framesize_regs
+= (TARGET_LARGE
? 4 : 2);
935 cfun
->machine
->need_to_save
[i
] = 0;
937 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
938 cfun
->machine
->framesize_locals
++;
940 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
941 + cfun
->machine
->framesize_locals
942 + cfun
->machine
->framesize_outgoing
);
946 is_attr_func (const char * attr
)
948 return lookup_attribute (attr
, DECL_ATTRIBUTES (current_function_decl
)) != NULL_TREE
;
951 /* Returns true if the current function has the "interrupt" attribute. */
954 msp430_is_interrupt_func (void)
956 if (current_function_decl
== NULL
)
958 return is_attr_func ("interrupt");
962 is_wakeup_func (void)
964 return msp430_is_interrupt_func () && is_attr_func ("wakeup");
970 return is_attr_func ("naked");
974 is_reentrant_func (void)
976 return is_attr_func ("reentrant");
980 is_critical_func (void)
982 return is_attr_func ("critical");
985 #undef TARGET_ASM_FUNCTION_PROLOGUE
986 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
989 msp430_start_function (FILE *outfile
, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED
)
993 fprintf (outfile
, "; start of function\n");
995 if (DECL_ATTRIBUTES (current_function_decl
) != NULL_TREE
)
997 fprintf (outfile
, "; attributes: ");
998 if (is_naked_func ())
999 fprintf (outfile
, "naked ");
1000 if (msp430_is_interrupt_func ())
1001 fprintf (outfile
, "interrupt ");
1002 if (is_reentrant_func ())
1003 fprintf (outfile
, "reentrant ");
1004 if (is_critical_func ())
1005 fprintf (outfile
, "critical ");
1006 if (is_wakeup_func ())
1007 fprintf (outfile
, "wakeup ");
1008 fprintf (outfile
, "\n");
1011 fprintf (outfile
, "; framesize_regs: %d\n", cfun
->machine
->framesize_regs
);
1012 fprintf (outfile
, "; framesize_locals: %d\n", cfun
->machine
->framesize_locals
);
1013 fprintf (outfile
, "; framesize_outgoing: %d\n", cfun
->machine
->framesize_outgoing
);
1014 fprintf (outfile
, "; framesize: %d\n", cfun
->machine
->framesize
);
1015 fprintf (outfile
, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, FRAME_POINTER_REGNUM
));
1016 fprintf (outfile
, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM
, STACK_POINTER_REGNUM
));
1019 fprintf (outfile
, "; saved regs:");
1020 for (r
= 0; r
< ARG_POINTER_REGNUM
; r
++)
1021 if (cfun
->machine
->need_to_save
[r
])
1023 fprintf (outfile
, " %s", reg_names
[r
]);
1027 fprintf (outfile
, "(none)");
1028 fprintf (outfile
, "\n");
1031 /* Common code to change the stack pointer. */
1033 increment_stack (HOST_WIDE_INT amount
)
1036 rtx sp
= stack_pointer_rtx
;
1043 inc
= GEN_INT (- amount
);
1045 F (emit_insn (gen_subpsi3 (sp
, sp
, inc
)));
1047 F (emit_insn (gen_subhi3 (sp
, sp
, inc
)));
1051 inc
= GEN_INT (amount
);
1053 emit_insn (gen_addpsi3 (sp
, sp
, inc
));
1055 emit_insn (gen_addhi3 (sp
, sp
, inc
));
1059 /* Verify MSP430 specific attributes. */
1062 msp430_attr (tree
* node
,
1065 int flags ATTRIBUTE_UNUSED
,
1066 bool * no_add_attrs
)
1068 gcc_assert (DECL_P (* node
));
1072 tree value
= TREE_VALUE (args
);
1074 switch (TREE_CODE (value
))
1077 if ( strcmp (TREE_STRING_POINTER (value
), "reset")
1078 && strcmp (TREE_STRING_POINTER (value
), "nmi")
1079 && strcmp (TREE_STRING_POINTER (value
), "watchdog"))
1080 /* Allow the attribute to be added - the linker script
1081 being used may still recognise this name. */
1082 warning (OPT_Wattributes
,
1083 "unrecognised interrupt vector argument of %qE attribute",
1088 if (wi::gtu_p (value
, 63))
1089 /* Allow the attribute to be added - the linker script
1090 being used may still recognise this value. */
1091 warning (OPT_Wattributes
,
1092 "numeric argument of %qE attribute must be in range 0..63",
1097 warning (OPT_Wattributes
,
1098 "argument of %qE attribute is not a string constant or number",
1100 *no_add_attrs
= true;
1105 if (TREE_CODE (* node
) != FUNCTION_DECL
)
1107 warning (OPT_Wattributes
,
1108 "%qE attribute only applies to functions",
1110 * no_add_attrs
= true;
1113 /* FIXME: We ought to check that the interrupt handler
1114 attribute has been applied to a void function. */
1115 /* FIXME: We should check that reentrant and critical
1116 functions are not naked and that critical functions
1117 are not reentrant. */
1122 #undef TARGET_ATTRIBUTE_TABLE
1123 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
1125 /* Table of MSP430-specific attributes. */
1126 const struct attribute_spec msp430_attribute_table
[] =
1128 /* Name min_len decl_req, fn_type_req, affects_type_identity
1129 max_len, type_req, handler. */
1130 { "interrupt", 0, 1, true, false, false, msp430_attr
, false },
1131 { "naked", 0, 0, true, false, false, msp430_attr
, false },
1132 { "reentrant", 0, 0, true, false, false, msp430_attr
, false },
1133 { "critical", 0, 0, true, false, false, msp430_attr
, false },
1134 { "wakeup", 0, 0, true, false, false, msp430_attr
, false },
1135 { NULL
, 0, 0, false, false, false, NULL
, false }
1139 msp430_start_function (FILE *file
, const char *name
, tree decl
)
1143 int_attr
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl
));
1144 if (int_attr
!= NULL_TREE
)
1146 tree intr_vector
= TREE_VALUE (int_attr
);
1148 if (intr_vector
!= NULL_TREE
)
1152 intr_vector
= TREE_VALUE (intr_vector
);
1154 /* The interrupt attribute has a vector value. Turn this into a
1155 section name, switch to that section and put the address of
1156 the current function into that vector slot. Note msp430_attr()
1157 has already verified the vector name for us. */
1158 if (TREE_CODE (intr_vector
) == STRING_CST
)
1159 sprintf (buf
, "__interrupt_vector_%.80s",
1160 TREE_STRING_POINTER (intr_vector
));
1161 else /* TREE_CODE (intr_vector) == INTEGER_CST */
1162 sprintf (buf
, "__interrupt_vector_%u",
1163 (unsigned int) TREE_INT_CST_LOW (intr_vector
));
1165 switch_to_section (get_section (buf
, SECTION_CODE
, decl
));
1166 fputs ("\t.word\t", file
);
1167 assemble_name (file
, name
);
1173 switch_to_section (function_section (decl
));
1174 ASM_OUTPUT_FUNCTION_LABEL (file
, name
, decl
);
1178 msp430_function_section (tree decl
, enum node_frequency freq
, bool startup
, bool exit
)
1180 /* In large mode we must make sure that interrupt handlers are put into
1181 low memory as the vector table only accepts 16-bit addresses. */
1183 && lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl
)))
1184 return get_section (".lowtext", SECTION_CODE
| SECTION_WRITE
, decl
);
1186 /* Otherwise, use the default function section. */
1187 return default_function_section (decl
, freq
, startup
, exit
);
1190 #undef TARGET_ASM_FUNCTION_SECTION
1191 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
1195 MSP430_BUILTIN_BIC_SR
,
1196 MSP430_BUILTIN_BIS_SR
,
1200 static GTY(()) tree msp430_builtins
[(int) MSP430_BUILTIN_max
];
1203 msp430_init_builtins (void)
1205 tree void_ftype_int
= build_function_type_list (void_type_node
, integer_type_node
, NULL
);
1207 msp430_builtins
[MSP430_BUILTIN_BIC_SR
] =
1208 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int
,
1209 MSP430_BUILTIN_BIC_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
1211 msp430_builtins
[MSP430_BUILTIN_BIS_SR
] =
1212 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int
,
1213 MSP430_BUILTIN_BIS_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
1217 msp430_builtin_decl (unsigned code
, bool initialize ATTRIBUTE_UNUSED
)
1221 case MSP430_BUILTIN_BIC_SR
:
1222 case MSP430_BUILTIN_BIS_SR
:
1223 return msp430_builtins
[code
];
1225 return error_mark_node
;
1230 msp430_expand_builtin (tree exp
,
1231 rtx target ATTRIBUTE_UNUSED
,
1232 rtx subtarget ATTRIBUTE_UNUSED
,
1233 enum machine_mode mode ATTRIBUTE_UNUSED
,
1234 int ignore ATTRIBUTE_UNUSED
)
1236 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
1237 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
1238 rtx arg1
= expand_normal (CALL_EXPR_ARG (exp
, 0));
1240 if (! msp430_is_interrupt_func ())
1242 error ("MSP430 builtin functions only work inside interrupt handlers");
1246 if (! REG_P (arg1
) && ! CONSTANT_P (arg1
))
1247 arg1
= force_reg (mode
, arg1
);
1251 case MSP430_BUILTIN_BIC_SR
: emit_insn (gen_bic_SR (arg1
)); break;
1252 case MSP430_BUILTIN_BIS_SR
: emit_insn (gen_bis_SR (arg1
)); break;
1254 internal_error ("bad builtin code");
1260 #undef TARGET_INIT_BUILTINS
1261 #define TARGET_INIT_BUILTINS msp430_init_builtins
1263 #undef TARGET_EXPAND_BUILTIN
1264 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
1266 #undef TARGET_BUILTIN_DECL
1267 #define TARGET_BUILTIN_DECL msp430_builtin_decl
1270 msp430_expand_prologue (void)
1274 /* Always use stack_pointer_rtx instead of calling
1275 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
1276 that there is a single rtx representing the stack pointer,
1277 namely stack_pointer_rtx, and uses == to recognize it. */
1278 rtx sp
= stack_pointer_rtx
;
1281 if (is_naked_func ())
1284 emit_insn (gen_prologue_start_marker ());
1286 if (is_critical_func ())
1288 emit_insn (gen_push_intr_state ());
1289 emit_insn (gen_disable_interrupts ());
1291 else if (is_reentrant_func ())
1292 emit_insn (gen_disable_interrupts ());
1294 if (!cfun
->machine
->computed
)
1295 msp430_compute_frame_info ();
1297 if (flag_stack_usage_info
)
1298 current_function_static_stack_size
= cfun
->machine
->framesize
;
1300 if (crtl
->args
.pretend_args_size
)
1304 gcc_assert (crtl
->args
.pretend_args_size
== 2);
1306 p
= emit_insn (gen_grow_and_swap ());
1308 /* Document the stack decrement... */
1309 note
= F (gen_rtx_SET (Pmode
, stack_pointer_rtx
,
1310 gen_rtx_MINUS (Pmode
, stack_pointer_rtx
, GEN_INT (2))));
1311 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
1313 /* ...and the establishment of a new location for the return address. */
1314 note
= F (gen_rtx_SET (Pmode
, gen_rtx_MEM (Pmode
,
1315 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, GEN_INT (-2))),
1317 add_reg_note (p
, REG_CFA_OFFSET
, note
);
1321 for (i
= 15; i
>= 4; i
--)
1322 if (cfun
->machine
->need_to_save
[i
])
1327 for (seq
= i
- 1; seq
>= 4 && cfun
->machine
->need_to_save
[seq
]; seq
--)
1333 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
1334 p
= F (emit_insn (gen_pushm (gen_rtx_REG (Pmode
, i
),
1337 note
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (count
+ 1));
1339 XVECEXP (note
, 0, 0)
1340 = F (gen_rtx_SET (VOIDmode
,
1342 gen_rtx_PLUS (Pmode
,
1344 GEN_INT (count
* (TARGET_LARGE
? -4 : -2)))));
1346 /* *sp-- = R[i-j] */
1350 for (j
= 0; j
< count
; j
++)
1353 int ofs
= (count
- j
- 1) * (TARGET_LARGE
? 4 : 2);
1356 addr
= gen_rtx_PLUS (Pmode
, sp
, GEN_INT (ofs
));
1358 addr
= stack_pointer_rtx
;
1360 XVECEXP (note
, 0, j
+ 1) =
1361 F (gen_rtx_SET (VOIDmode
,
1362 gen_rtx_MEM (Pmode
, addr
),
1363 gen_rtx_REG (Pmode
, i
- j
)) );
1366 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
1370 F (emit_insn (gen_push (gen_rtx_REG (Pmode
, i
))));
1373 if (frame_pointer_needed
)
1374 F (emit_move_insn (gen_rtx_REG (Pmode
, FRAME_POINTER_REGNUM
), sp
));
1376 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1378 increment_stack (- fs
);
1380 emit_insn (gen_prologue_end_marker ());
1384 msp430_expand_epilogue (int is_eh
)
1390 if (is_naked_func ())
1393 if (cfun
->machine
->need_to_save
[10])
1395 /* Check for a helper function. */
1396 helper_n
= 7; /* For when the loop below never sees a match. */
1397 for (i
= 9; i
>= 4; i
--)
1398 if (!cfun
->machine
->need_to_save
[i
])
1402 if (cfun
->machine
->need_to_save
[i
])
1411 emit_insn (gen_epilogue_start_marker ());
1413 if (cfun
->decl
&& strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun
->decl
)), "main") == 0)
1414 emit_insn (gen_msp430_refsym_need_exit ());
1416 if (is_wakeup_func ())
1417 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
1418 status register current residing on the stack. When this function
1419 executes its RETI instruction the SR will be updated with this saved
1420 value, thus ensuring that the processor is woken up from any low power
1421 state in which it may be residing. */
1422 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
1424 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1426 increment_stack (fs
);
1430 /* We need to add the right "SP" register save just after the
1431 regular ones, so that when we pop it off we're in the EH
1432 return frame, not this one. This overwrites our own return
1433 address, but we're not going to be returning anyway. */
1434 rtx r12
= gen_rtx_REG (Pmode
, 12);
1435 rtx (*addPmode
)(rtx
, rtx
, rtx
) = TARGET_LARGE
? gen_addpsi3
: gen_addhi3
;
1437 /* R12 will hold the new SP. */
1438 i
= cfun
->machine
->framesize_regs
;
1439 emit_move_insn (r12
, stack_pointer_rtx
);
1440 emit_insn (addPmode (r12
, r12
, EH_RETURN_STACKADJ_RTX
));
1441 emit_insn (addPmode (r12
, r12
, GEN_INT (i
)));
1442 emit_move_insn (gen_rtx_MEM (Pmode
, plus_constant (Pmode
, stack_pointer_rtx
, i
)), r12
);
1445 for (i
= 4; i
<= 15; i
++)
1446 if (cfun
->machine
->need_to_save
[i
])
1450 for (seq
= i
+ 1; seq
<= 15 && cfun
->machine
->need_to_save
[seq
]; seq
++)
1456 /* Note: With TARGET_LARGE we still use
1457 POPM as POPX.A is two bytes bigger. */
1458 emit_insn (gen_popm (stack_pointer_rtx
, GEN_INT (seq
- 1),
1462 else if (i
== 11 - helper_n
1463 && ! msp430_is_interrupt_func ()
1464 && ! is_reentrant_func ()
1465 && ! is_critical_func ()
1466 && crtl
->args
.pretend_args_size
== 0
1467 /* Calling the helper takes as many bytes as the POP;RET sequence. */
1471 emit_insn (gen_epilogue_helper (GEN_INT (helper_n
)));
1475 emit_insn (gen_pop (gen_rtx_REG (Pmode
, i
)));
1480 /* Also pop SP, which puts us into the EH return frame. Except
1481 that you can't "pop" sp, you have to just load it off the
1483 emit_move_insn (stack_pointer_rtx
, gen_rtx_MEM (Pmode
, stack_pointer_rtx
));
1486 if (crtl
->args
.pretend_args_size
)
1487 emit_insn (gen_swap_and_shrink ());
1489 if (is_critical_func ())
1490 emit_insn (gen_pop_intr_state ());
1491 else if (is_reentrant_func ())
1492 emit_insn (gen_enable_interrupts ());
1494 emit_jump_insn (gen_msp_return ());
1497 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
1498 m32c_emit_eh_epilogue. */
1500 msp430_eh_return_stackadj_rtx (void)
1502 if (!cfun
->machine
->eh_stack_adjust
)
1506 sa
= gen_rtx_REG (Pmode
, 15);
1507 cfun
->machine
->eh_stack_adjust
= sa
;
1509 return cfun
->machine
->eh_stack_adjust
;
1512 /* This function is called before reload, to "fix" the stack in
1513 preparation for an EH return. */
1515 msp430_expand_eh_return (rtx eh_handler
)
1517 /* These are all Pmode */
1518 rtx ap
, sa
, ra
, tmp
;
1520 ap
= arg_pointer_rtx
;
1521 sa
= msp430_eh_return_stackadj_rtx ();
1525 tmp
= gen_rtx_PLUS (Pmode
, ap
, sa
);
1526 tmp
= plus_constant (Pmode
, tmp
, TARGET_LARGE
? -4 : -2);
1527 tmp
= gen_rtx_MEM (Pmode
, tmp
);
1528 emit_move_insn (tmp
, ra
);
1531 /* This is a list of MD patterns that implement fixed-count shifts. */
1537 rtx (*genfunc
)(rtx
,rtx
);
1539 const_shift_helpers
[] =
1541 #define CSH(N,C,X,G) { "__mspabi_"N, C, X, gen_##G }
1543 CSH ("slli", 1, 1, slli_1
),
1544 CSH ("slll", 1, 1, slll_1
),
1545 CSH ("slll", 2, 1, slll_2
),
1547 CSH ("srai", 1, 0, srai_1
),
1548 CSH ("sral", 1, 0, sral_1
),
1549 CSH ("sral", 2, 0, sral_2
),
1551 CSH ("srll", 1, 0, srll_1
),
1552 CSH ("srll", 2, 1, srll_2x
),
1557 /* The MSP430 ABI defines a number of helper functions that should be
1558 used for, for example, 32-bit shifts. This function is called to
1559 emit such a function, using the table above to optimize some
1562 msp430_expand_helper (rtx
*operands
, const char *helper_name
, bool const_variants
)
1565 char *helper_const
= NULL
;
1568 enum machine_mode arg0mode
= GET_MODE (operands
[0]);
1569 enum machine_mode arg1mode
= GET_MODE (operands
[1]);
1570 enum machine_mode arg2mode
= GET_MODE (operands
[2]);
1571 int have_430x
= msp430x
? 1 : 0;
1573 if (CONST_INT_P (operands
[2]))
1577 for (i
=0; const_shift_helpers
[i
].name
; i
++)
1579 if (const_shift_helpers
[i
].need_430x
<= have_430x
1580 && strcmp (helper_name
, const_shift_helpers
[i
].name
) == 0
1581 && INTVAL (operands
[2]) == const_shift_helpers
[i
].count
)
1583 emit_insn (const_shift_helpers
[i
].genfunc (operands
[0], operands
[1]));
1589 if (arg1mode
== VOIDmode
)
1590 arg1mode
= arg0mode
;
1591 if (arg2mode
== VOIDmode
)
1592 arg2mode
= arg0mode
;
1594 if (arg1mode
== SImode
)
1601 && CONST_INT_P (operands
[2])
1602 && INTVAL (operands
[2]) >= 1
1603 && INTVAL (operands
[2]) <= 15)
1605 /* Note that the INTVAL is limited in value and length by the conditional above. */
1606 int len
= strlen (helper_name
) + 4;
1607 helper_const
= (char *) xmalloc (len
);
1608 snprintf (helper_const
, len
, "%s_%d", helper_name
, (int) INTVAL (operands
[2]));
1611 emit_move_insn (gen_rtx_REG (arg1mode
, 12),
1614 emit_move_insn (gen_rtx_REG (arg2mode
, arg2
),
1617 c
= gen_call_value_internal (gen_rtx_REG (arg0mode
, 12),
1618 gen_rtx_SYMBOL_REF (VOIDmode
, helper_const
? helper_const
: helper_name
),
1620 c
= emit_call_insn (c
);
1621 RTL_CONST_CALL_P (c
) = 1;
1624 use_regs (&f
, 12, arg1sz
);
1626 use_regs (&f
, arg2
, 1);
1627 add_function_usage_to (c
, f
);
1629 emit_move_insn (operands
[0],
1630 gen_rtx_REG (arg0mode
, 12));
1633 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
1635 msp430_fixup_compare_operands (enum machine_mode my_mode
, rtx
* operands
)
1637 /* constants we're looking for, not constants which are allowed. */
1638 int const_op_idx
= 1;
1640 if (msp430_reversible_cmp_operator (operands
[0], VOIDmode
))
1643 if (GET_CODE (operands
[const_op_idx
]) != REG
1644 && GET_CODE (operands
[const_op_idx
]) != MEM
)
1645 operands
[const_op_idx
] = copy_to_mode_reg (my_mode
, operands
[const_op_idx
]);
1648 /* Simplify_gen_subreg() doesn't handle memory references the way we
1649 need it to below, so we use this function for when we must get a
1650 valid subreg in a "natural" state. */
1652 msp430_subreg (enum machine_mode mode
, rtx r
, enum machine_mode omode
, int byte
)
1656 if (GET_CODE (r
) == SUBREG
1657 && SUBREG_BYTE (r
) == 0)
1659 rtx ireg
= SUBREG_REG (r
);
1660 enum machine_mode imode
= GET_MODE (ireg
);
1662 /* special case for (HI (SI (PSI ...), 0)) */
1663 if (imode
== PSImode
1666 rv
= gen_rtx_SUBREG (mode
, ireg
, byte
);
1668 rv
= simplify_gen_subreg (mode
, ireg
, imode
, byte
);
1670 else if (GET_CODE (r
) == MEM
)
1671 rv
= adjust_address (r
, mode
, byte
);
1673 rv
= simplify_gen_subreg (mode
, r
, omode
, byte
);
1681 /* Called by movsi_x to generate the HImode operands. */
1683 msp430_split_movsi (rtx
*operands
)
1685 rtx op00
, op02
, op10
, op12
;
1687 op00
= msp430_subreg (HImode
, operands
[0], SImode
, 0);
1688 op02
= msp430_subreg (HImode
, operands
[0], SImode
, 2);
1690 if (GET_CODE (operands
[1]) == CONST
1691 || GET_CODE (operands
[1]) == SYMBOL_REF
)
1693 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
1694 op10
= gen_rtx_CONST (HImode
, op10
);
1695 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
1696 op12
= gen_rtx_CONST (HImode
, op12
);
1700 op10
= msp430_subreg (HImode
, operands
[1], SImode
, 0);
1701 op12
= msp430_subreg (HImode
, operands
[1], SImode
, 2);
1704 if (rtx_equal_p (operands
[0], operands
[1]))
1711 else if (rtx_equal_p (op00
, op12
)
1712 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
1713 || (REG_P (op00
) && reg_mentioned_p (op00
, op10
))
1714 /* Or storing (rN) into mem (rN). */
1715 || (REG_P (op10
) && reg_mentioned_p (op10
, op00
))
1733 /* The MSPABI specifies the names of various helper functions, many of
1734 which are compatible with GCC's helpers. This table maps the GCC
1735 name to the MSPABI name. */
1738 char const * const gcc_name
;
1739 char const * const ti_name
;
1741 helper_function_name_mappings
[] =
1743 /* Floating point to/from integer conversions. */
1744 { "__truncdfsf2", "__mspabi_cvtdf" },
1745 { "__extendsfdf2", "__mspabi_cvtfd" },
1746 { "__fixdfhi", "__mspabi_fixdi" },
1747 { "__fixdfsi", "__mspabi_fixdli" },
1748 { "__fixdfdi", "__mspabi_fixdlli" },
1749 { "__fixunsdfhi", "__mspabi_fixdu" },
1750 { "__fixunsdfsi", "__mspabi_fixdul" },
1751 { "__fixunsdfdi", "__mspabi_fixdull" },
1752 { "__fixsfhi", "__mspabi_fixfi" },
1753 { "__fixsfsi", "__mspabi_fixfli" },
1754 { "__fixsfdi", "__mspabi_fixflli" },
1755 { "__fixunsfhi", "__mspabi_fixfu" },
1756 { "__fixunsfsi", "__mspabi_fixful" },
1757 { "__fixunsfdi", "__mspabi_fixfull" },
1758 { "__floathisf", "__mspabi_fltif" },
1759 { "__floatsisf", "__mspabi_fltlif" },
1760 { "__floatdisf", "__mspabi_fltllif" },
1761 { "__floathidf", "__mspabi_fltid" },
1762 { "__floatsidf", "__mspabi_fltlid" },
1763 { "__floatdidf", "__mspabi_fltllid" },
1764 { "__floatunhisf", "__mspabi_fltuf" },
1765 { "__floatunsisf", "__mspabi_fltulf" },
1766 { "__floatundisf", "__mspabi_fltullf" },
1767 { "__floatunhidf", "__mspabi_fltud" },
1768 { "__floatunsidf", "__mspabi_fltuld" },
1769 { "__floatundidf", "__mspabi_fltulld" },
1771 /* Floating point comparisons. */
1772 /* GCC uses individual functions for each comparison, TI uses one
1773 compare <=> function. */
1775 /* Floating point arithmatic */
1776 { "__adddf3", "__mspabi_addd" },
1777 { "__addsf3", "__mspabi_addf" },
1778 { "__divdf3", "__mspabi_divd" },
1779 { "__divsf3", "__mspabi_divf" },
1780 { "__muldf3", "__mspabi_mpyd" },
1781 { "__mulsf3", "__mspabi_mpyf" },
1782 { "__subdf3", "__mspabi_subd" },
1783 { "__subsf3", "__mspabi_subf" },
1784 /* GCC does not use helper functions for negation */
1786 /* Integer multiply, divide, remainder. */
1787 { "__mulhi3", "__mspabi_mpyi" },
1788 { "__mulsi3", "__mspabi_mpyl" },
1789 { "__muldi3", "__mspabi_mpyll" },
1791 /* Clarify signed vs unsigned first. */
1792 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
1793 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
1796 { "__divhi3", "__mspabi_divi" },
1797 { "__divsi3", "__mspabi_divli" },
1798 { "__divdi3", "__mspabi_divlli" },
1799 { "__udivhi3", "__mspabi_divu" },
1800 { "__udivsi3", "__mspabi_divlu" },
1801 { "__udivdi3", "__mspabi_divllu" },
1802 { "__modhi3", "__mspabi_remi" },
1803 { "__modsi3", "__mspabi_remli" },
1804 { "__moddi3", "__mspabi_remlli" },
1805 { "__umodhi3", "__mspabi_remu" },
1806 { "__umodsi3", "__mspabi_remul" },
1807 { "__umoddi3", "__mspabi_remull" },
1809 /* Bitwise operations. */
1810 /* Rotation - no rotation support yet. */
1811 /* Logical left shift - gcc already does these itself. */
1812 /* Arithmetic left shift - gcc already does these itself. */
1813 /* Arithmetic right shift - gcc already does these itself. */
1818 /* Returns true if the current MCU is an F5xxx series. */
1820 msp430_use_f5_series_hwmult (void)
1822 if (msp430_hwmult_type
== F5SERIES
)
1825 if (target_mcu
== NULL
|| msp430_hwmult_type
!= AUTO
)
1828 return strncasecmp (target_mcu
, "msp430f5", 8) == 0;
1831 /* Returns true id the current MCU has a second generation 32-bit hardware multiplier. */
1833 use_32bit_hwmult (void)
1835 static const char * known_32bit_mult_mcus
[] =
1837 "msp430f4783", "msp430f4793", "msp430f4784",
1838 "msp430f4794", "msp430f47126", "msp430f47127",
1839 "msp430f47163", "msp430f47173", "msp430f47183",
1840 "msp430f47193", "msp430f47166", "msp430f47176",
1841 "msp430f47186", "msp430f47196", "msp430f47167",
1842 "msp430f47177", "msp430f47187", "msp430f47197"
1846 if (msp430_hwmult_type
== LARGE
)
1849 if (target_mcu
== NULL
|| msp430_hwmult_type
!= AUTO
)
1852 for (i
= ARRAY_SIZE (known_32bit_mult_mcus
); i
--;)
1853 if (strcasecmp (target_mcu
, known_32bit_mult_mcus
[i
]) == 0)
1859 /* This function does the same as the default, but it will replace GCC
1860 function names with the MSPABI-specified ones. */
1862 msp430_output_labelref (FILE *file
, const char *name
)
1866 for (i
= 0; helper_function_name_mappings
[i
].gcc_name
; i
++)
1867 if (strcmp (helper_function_name_mappings
[i
].gcc_name
, name
) == 0)
1869 name
= helper_function_name_mappings
[i
].ti_name
;
1873 /* If we have been given a specific MCU name then we may be
1874 able to make use of its hardware multiply capabilities. */
1875 if (msp430_hwmult_type
!= NONE
)
1877 if (strcmp ("__mspabi_mpyi", name
) == 0)
1879 if (msp430_use_f5_series_hwmult ())
1880 name
= "__mulhi2_f5";
1884 else if (strcmp ("__mspabi_mpyl", name
) == 0)
1886 if (msp430_use_f5_series_hwmult ())
1887 name
= "__mulsi2_f5";
1888 else if (use_32bit_hwmult ())
1889 name
= "__mulsi2_hw32";
1898 /* Common code for msp430_print_operand... */
1901 msp430_print_operand_raw (FILE * file
, rtx op
)
1905 switch (GET_CODE (op
))
1908 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
1914 fprintf (file
, "%#" HOST_WIDE_INT_PRINT
"x", i
);
1916 fprintf (file
, "%" HOST_WIDE_INT_PRINT
"d", i
);
1924 output_addr_const (file
, op
);
1928 print_rtl (file
, op
);
1933 #undef TARGET_PRINT_OPERAND_ADDRESS
1934 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
1936 /* Output to stdio stream FILE the assembler syntax for an
1937 instruction operand that is a memory reference whose address
1941 msp430_print_operand_addr (FILE * file
, rtx addr
)
1943 switch (GET_CODE (addr
))
1946 msp430_print_operand_raw (file
, XEXP (addr
, 1));
1947 gcc_assert (REG_P (XEXP (addr
, 0)));
1948 fprintf (file
, "(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
1952 fprintf (file
, "@");
1959 fprintf (file
, "&");
1966 msp430_print_operand_raw (file
, addr
);
1969 #undef TARGET_PRINT_OPERAND
1970 #define TARGET_PRINT_OPERAND msp430_print_operand
1972 /* A low 16-bits of int/lower of register pair
1973 B high 16-bits of int/higher of register pair
1974 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
1975 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
1976 H like %B (for backwards compatibility)
1978 J an integer without a # prefix
1979 L like %A (for backwards compatibility)
1980 O offset of the top of the stack
1981 Q like X but generates an A postfix
1982 R inverse of condition code, unsigned.
1983 X X instruction postfix in large mode
1986 b .B or .W or .A, depending upon the mode
1988 r inverse of condition code
1989 x like X but only for pointers. */
1992 msp430_print_operand (FILE * file
, rtx op
, int letter
)
1996 /* We can't use c, n, a, or l. */
2000 gcc_assert (CONST_INT_P (op
));
2001 /* Print the constant value, less one. */
2002 fprintf (file
, "#%ld", INTVAL (op
) - 1);
2005 gcc_assert (CONST_INT_P (op
));
2006 /* Print the constant value, less four. */
2007 fprintf (file
, "#%ld", INTVAL (op
) - 4);
2010 if (GET_CODE (op
) == CONST_INT
)
2012 /* Inverse of constants */
2013 int i
= INTVAL (op
);
2014 fprintf (file
, "%d", ~i
);
2019 case 'r': /* Conditional jump where the condition is reversed. */
2020 switch (GET_CODE (op
))
2022 case EQ
: fprintf (file
, "NE"); break;
2023 case NE
: fprintf (file
, "EQ"); break;
2024 case GEU
: fprintf (file
, "LO"); break;
2025 case LTU
: fprintf (file
, "HS"); break;
2026 case GE
: fprintf (file
, "L"); break;
2027 case LT
: fprintf (file
, "GE"); break;
2028 /* Assume these have reversed operands. */
2029 case GTU
: fprintf (file
, "HS"); break;
2030 case LEU
: fprintf (file
, "LO"); break;
2031 case GT
: fprintf (file
, "GE"); break;
2032 case LE
: fprintf (file
, "L"); break;
2034 msp430_print_operand_raw (file
, op
);
2038 case 'R': /* Conditional jump where the operands are reversed. */
2039 switch (GET_CODE (op
))
2041 case GTU
: fprintf (file
, "LO"); break;
2042 case LEU
: fprintf (file
, "HS"); break;
2043 case GT
: fprintf (file
, "L"); break;
2044 case LE
: fprintf (file
, "GE"); break;
2046 msp430_print_operand_raw (file
, op
);
2050 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
2051 gcc_assert (CONST_INT_P (op
));
2052 fprintf (file
, "#%d", 1 << INTVAL (op
));
2055 switch (GET_MODE (op
))
2057 case QImode
: fprintf (file
, ".B"); return;
2058 case HImode
: fprintf (file
, ".W"); return;
2059 case PSImode
: fprintf (file
, ".A"); return;
2060 case SImode
: fprintf (file
, ".A"); return;
2065 case 'L': /* Low half. */
2066 switch (GET_CODE (op
))
2069 op
= adjust_address (op
, Pmode
, 0);
2074 op
= GEN_INT (INTVAL (op
) & 0xffff);
2078 /* If you get here, figure out a test case :-) */
2083 case 'H': /* high half */
2084 switch (GET_CODE (op
))
2087 op
= adjust_address (op
, Pmode
, 2);
2090 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 1);
2093 op
= GEN_INT (INTVAL (op
) >> 16);
2097 /* If you get here, figure out a test case :-) */
2102 switch (GET_CODE (op
))
2105 op
= adjust_address (op
, Pmode
, 3);
2108 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 2);
2111 op
= GEN_INT ((long long) INTVAL (op
) >> 32);
2115 /* If you get here, figure out a test case :-) */
2120 switch (GET_CODE (op
))
2123 op
= adjust_address (op
, Pmode
, 4);
2126 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 3);
2129 op
= GEN_INT ((long long) INTVAL (op
) >> 48);
2133 /* If you get here, figure out a test case :-) */
2139 /* This is used to turn, for example, an ADD opcode into an ADDX
2140 opcode when we're using 20-bit addresses. */
2142 fprintf (file
, "X");
2143 /* We don't care which operand we use, but we want 'X' in the MD
2144 file, so we do it this way. */
2148 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
2149 if (TARGET_LARGE
&& GET_MODE (op
) == PSImode
)
2150 fprintf (file
, "X");
2154 /* Likewise, for BR -> BRA. */
2156 fprintf (file
, "A");
2160 /* Computes the offset to the top of the stack for the current frame.
2161 This has to be done here rather than in, say, msp430_expand_builtin()
2162 because builtins are expanded before the frame layout is determined. */
2163 fprintf (file
, "%d",
2164 msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, STACK_POINTER_REGNUM
)
2169 gcc_assert (GET_CODE (op
) == CONST_INT
);
2173 output_operand_lossage ("invalid operand prefix");
2177 switch (GET_CODE (op
))
2180 msp430_print_operand_raw (file
, op
);
2184 addr
= XEXP (op
, 0);
2185 msp430_print_operand_addr (file
, addr
);
2193 fprintf (file
, "#");
2194 msp430_print_operand_raw (file
, op
);
2197 case EQ
: fprintf (file
, "EQ"); break;
2198 case NE
: fprintf (file
, "NE"); break;
2199 case GEU
: fprintf (file
, "HS"); break;
2200 case LTU
: fprintf (file
, "LO"); break;
2201 case GE
: fprintf (file
, "GE"); break;
2202 case LT
: fprintf (file
, "L"); break;
2205 print_rtl (file
, op
);
2214 msp430_return_addr_rtx (int count
)
2220 ra_size
= TARGET_LARGE
? 4 : 2;
2221 if (crtl
->args
.pretend_args_size
)
2224 return gen_rtx_MEM (Pmode
, gen_rtx_PLUS (Pmode
, arg_pointer_rtx
, GEN_INT (- ra_size
)));
2228 msp430_incoming_return_addr_rtx (void)
2230 return gen_rtx_MEM (Pmode
, stack_pointer_rtx
);
2233 /* Instruction generation stuff. */
2235 /* Generate a sequence of instructions to sign-extend an HI
2236 value into an SI value. Handles the tricky case where
2237 we are overwriting the destination. */
2240 msp430x_extendhisi (rtx
* operands
)
2242 if (REGNO (operands
[0]) == REGNO (operands
[1]))
2243 /* Low word of dest == source word. */
2244 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
2247 /* Note: This sequence is approximately the same length as invoking a helper
2248 function to perform the sign-extension, as in:
2252 CALL __mspabi_srai_15
2255 but this version does not involve any function calls or using argument
2256 registers, so it reduces register pressure. */
2257 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
2259 if (REGNO (operands
[0]) + 1 == REGNO (operands
[1]))
2260 /* High word of dest == source word. */
2261 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
2263 /* No overlap between dest and source. */
2264 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
2267 /* Likewise for logical right shifts. */
2269 msp430x_logical_shift_right (rtx amount
)
2271 /* The MSP430X's logical right shift instruction - RRUM - does
2272 not use an extension word, so we cannot encode a repeat count.
2273 Try various alternatives to work around this. If the count
2274 is in a register we are stuck, hence the assert. */
2275 gcc_assert (CONST_INT_P (amount
));
2277 if (INTVAL (amount
) <= 0
2278 || INTVAL (amount
) >= 16)
2279 return "# nop logical shift.";
2281 if (INTVAL (amount
) > 0
2282 && INTVAL (amount
) < 5)
2283 return "rrum.w\t%2, %0"; /* Two bytes. */
2285 if (INTVAL (amount
) > 4
2286 && INTVAL (amount
) < 9)
2287 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
2289 /* First we logically shift right by one. Now we know
2290 that the top bit is zero and we can use the arithmetic
2291 right shift instruction to perform the rest of the shift. */
2292 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
2295 struct gcc_target targetm
= TARGET_INITIALIZER
;
2297 #include "gt-msp430.h"