1 /* Subroutines used for code generation on TI MSP430 processors.
2 Copyright (C) 2012-2015 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"
28 #include "double-int.h"
35 #include "fold-const.h"
36 #include "stor-layout.h"
40 #include "hard-reg-set.h"
41 #include "insn-config.h"
42 #include "conditions.h"
44 #include "insn-attr.h"
49 #include "insn-codes.h"
53 #include "diagnostic-core.h"
56 #include "dominance.h"
62 #include "cfgcleanup.h"
64 #include "basic-block.h"
70 #include "target-def.h"
71 #include "langhooks.h"
72 #include "msp430-protos.h"
78 static void msp430_compute_frame_info (void);
82 /* Run-time Target Specification. */
86 struct GTY(()) machine_function
88 /* If set, the rest of the fields have been computed. */
90 /* Which registers need to be saved in the pro/epilogue. */
91 int need_to_save
[FIRST_PSEUDO_REGISTER
];
93 /* These fields describe the frame layout... */
95 /* 2/4 bytes for saved PC */
99 int framesize_outgoing
;
103 /* How much we adjust the stack when returning from an exception
108 /* This is our init_machine_status, as set in
109 msp_option_override. */
110 static struct machine_function
*
111 msp430_init_machine_status (void)
113 struct machine_function
*m
;
115 m
= ggc_cleared_alloc
<machine_function
> ();
120 #undef TARGET_OPTION_OVERRIDE
121 #define TARGET_OPTION_OVERRIDE msp430_option_override
123 static const char * msp430_mcu_names
[] =
125 "msp430afe221", "msp430afe222", "msp430afe223", "msp430afe231",
126 "msp430afe232", "msp430afe233", "msp430afe251", "msp430afe252",
127 "msp430afe253", "msp430c091", "msp430c092", "msp430c111",
128 "msp430c1111", "msp430c112", "msp430c1121", "msp430c1331",
129 "msp430c1351", "msp430c311s", "msp430c312", "msp430c313",
130 "msp430c314", "msp430c315", "msp430c323", "msp430c325",
131 "msp430c336", "msp430c337", "msp430c412", "msp430c413",
132 "msp430e112", "msp430e313", "msp430e315", "msp430e325",
133 "msp430e337", "msp430f110", "msp430f1101", "msp430f1101a",
134 "msp430f1111", "msp430f1111a", "msp430f112", "msp430f1121",
135 "msp430f1121a", "msp430f1122", "msp430f1132", "msp430f122",
136 "msp430f1222", "msp430f123", "msp430f1232", "msp430f133",
137 "msp430f135", "msp430f147", "msp430f1471", "msp430f148",
138 "msp430f1481", "msp430f149", "msp430f1491", "msp430f155",
139 "msp430f156", "msp430f157", "msp430f1610", "msp430f1611",
140 "msp430f1612", "msp430f167", "msp430f168", "msp430f169",
141 "msp430f2001", "msp430f2002", "msp430f2003", "msp430f2011",
142 "msp430f2012", "msp430f2013", "msp430f2101", "msp430f2111",
143 "msp430f2112", "msp430f2121", "msp430f2122", "msp430f2131",
144 "msp430f2132", "msp430f2232", "msp430f2234", "msp430f2252",
145 "msp430f2254", "msp430f2272", "msp430f2274", "msp430f233",
146 "msp430f2330", "msp430f235", "msp430f2350", "msp430f2370",
147 "msp430f2410", "msp430f247", "msp430f2471", "msp430f248",
148 "msp430f2481", "msp430f249", "msp430f2491", "msp430f412",
149 "msp430f413", "msp430f4132", "msp430f415", "msp430f4152",
150 "msp430f417", "msp430f423", "msp430f423a", "msp430f425",
151 "msp430f4250", "msp430f425a", "msp430f4260", "msp430f427",
152 "msp430f4270", "msp430f427a", "msp430f435", "msp430f4351",
153 "msp430f436", "msp430f4361", "msp430f437", "msp430f4371",
154 "msp430f438", "msp430f439", "msp430f447", "msp430f448",
155 "msp430f4481", "msp430f449", "msp430f4491", "msp430f477",
156 "msp430f478", "msp430f4783", "msp430f4784", "msp430f479",
157 "msp430f4793", "msp430f4794", "msp430fe423", "msp430fe4232",
158 "msp430fe423a", "msp430fe4242", "msp430fe425", "msp430fe4252",
159 "msp430fe425a", "msp430fe427", "msp430fe4272", "msp430fe427a",
160 "msp430fg4250", "msp430fg4260", "msp430fg4270", "msp430fg437",
161 "msp430fg438", "msp430fg439", "msp430fg477", "msp430fg478",
162 "msp430fg479", "msp430fw423", "msp430fw425", "msp430fw427",
163 "msp430fw428", "msp430fw429", "msp430g2001", "msp430g2101",
164 "msp430g2102", "msp430g2111", "msp430g2112", "msp430g2113",
165 "msp430g2121", "msp430g2131", "msp430g2132", "msp430g2152",
166 "msp430g2153", "msp430g2201", "msp430g2202", "msp430g2203",
167 "msp430g2210", "msp430g2211", "msp430g2212", "msp430g2213",
168 "msp430g2221", "msp430g2230", "msp430g2231", "msp430g2232",
169 "msp430g2233", "msp430g2252", "msp430g2253", "msp430g2302",
170 "msp430g2303", "msp430g2312", "msp430g2313", "msp430g2332",
171 "msp430g2333", "msp430g2352", "msp430g2353", "msp430g2402",
172 "msp430g2403", "msp430g2412", "msp430g2413", "msp430g2432",
173 "msp430g2433", "msp430g2444", "msp430g2452", "msp430g2453",
174 "msp430g2513", "msp430g2533", "msp430g2544", "msp430g2553",
175 "msp430g2744", "msp430g2755", "msp430g2855", "msp430g2955",
176 "msp430i2020", "msp430i2021", "msp430i2030", "msp430i2031",
177 "msp430i2040", "msp430i2041", "msp430l092", "msp430p112",
178 "msp430p313", "msp430p315", "msp430p315s", "msp430p325",
179 "msp430p337", "msp430tch5e"
182 /* Generate a C preprocessor symbol based upon the MCU selected by the user.
183 If a specific MCU has not been selected then return a generic symbol instead. */
186 msp430_mcu_name (void)
191 static char mcu_name
[64];
193 snprintf (mcu_name
, sizeof (mcu_name
) - 1, "__%s__", target_mcu
);
194 for (i
= strlen (mcu_name
); i
--;)
195 mcu_name
[i
] = TOUPPER (mcu_name
[i
]);
199 return msp430x
? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
203 msp430_option_override (void)
205 init_machine_status
= msp430_init_machine_status
;
209 if (strcasecmp (target_cpu
, "msp430x") == 0)
211 else /* target_cpu == "msp430" - already handled by the front end. */
214 /* Note - the front end has already ensured at most
215 one of target_cpu and target_mcu will be set. */
220 /* If we are given an MCU name, we assume that it supports 430X.
221 Then we check to see if it is one of the known MCUs that only
225 for (i
= ARRAY_SIZE (msp430_mcu_names
); i
--;)
226 if (strcasecmp (msp430_mcu_names
[i
], target_mcu
) == 0)
231 /* It is not an error if we do not match the MCU name. There are
235 if (TARGET_LARGE
&& !msp430x
)
236 error ("-mlarge requires a 430X-compatible -mmcu=");
238 if (flag_exceptions
|| flag_non_call_exceptions
239 || flag_unwind_tables
|| flag_asynchronous_unwind_tables
)
240 flag_omit_frame_pointer
= false;
242 flag_omit_frame_pointer
= true;
244 /* This is a hack to work around a problem with the newlib build
245 mechanism. Newlib always appends CFLAGS to the end of the GCC
246 command line and always sets -O2 in CFLAGS. Thus it is not
247 possible to build newlib with -Os enabled. Until now... */
248 if (TARGET_OPT_SPACE
&& optimize
< 3)
252 #undef TARGET_SCALAR_MODE_SUPPORTED_P
253 #define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
256 msp430_scalar_mode_supported_p (machine_mode m
)
258 if (m
== PSImode
&& msp430x
)
264 return default_scalar_mode_supported_p (m
);
271 #undef TARGET_MS_BITFIELD_LAYOUT_P
272 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
275 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED
)
284 /* Implements HARD_REGNO_NREGS. MSP430X registers can hold a single
285 PSImode value, but not an SImode value. */
287 msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED
,
290 if (mode
== PSImode
&& msp430x
)
292 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
296 /* Implements HARD_REGNO_NREGS_HAS_PADDING. */
298 msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED
,
301 if (mode
== PSImode
&& msp430x
)
303 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
307 /* Implements HARD_REGNO_NREGS_WITH_PADDING. */
309 msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED
,
314 return msp430_hard_regno_nregs (regno
, mode
);
317 /* Implements HARD_REGNO_MODE_OK. */
319 msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED
,
322 return regno
<= (ARG_POINTER_REGNUM
- msp430_hard_regno_nregs (regno
, mode
));
325 /* Implements MODES_TIEABLE_P. */
327 msp430_modes_tieable_p (machine_mode mode1
, machine_mode mode2
)
329 if ((mode1
== PSImode
|| mode2
== SImode
)
330 || (mode1
== SImode
|| mode2
== PSImode
))
333 return ((GET_MODE_CLASS (mode1
) == MODE_FLOAT
334 || GET_MODE_CLASS (mode1
) == MODE_COMPLEX_FLOAT
)
335 == (GET_MODE_CLASS (mode2
) == MODE_FLOAT
336 || GET_MODE_CLASS (mode2
) == MODE_COMPLEX_FLOAT
));
339 #undef TARGET_FRAME_POINTER_REQUIRED
340 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
343 msp430_frame_pointer_required (void)
348 #undef TARGET_CAN_ELIMINATE
349 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
352 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED
,
353 const int to_reg ATTRIBUTE_UNUSED
)
358 /* Implements INITIAL_ELIMINATION_OFFSET. */
360 msp430_initial_elimination_offset (int from
, int to
)
362 int rv
= 0; /* As if arg to arg. */
364 msp430_compute_frame_info ();
368 case STACK_POINTER_REGNUM
:
369 rv
+= cfun
->machine
->framesize_outgoing
;
370 rv
+= cfun
->machine
->framesize_locals
;
372 case FRAME_POINTER_REGNUM
:
373 rv
+= cfun
->machine
->framesize_regs
;
374 /* Allow for the saved return address. */
375 rv
+= (TARGET_LARGE
? 4 : 2);
376 /* NB/ No need to allow for crtl->args.pretend_args_size.
377 GCC does that for us. */
385 case FRAME_POINTER_REGNUM
:
386 /* Allow for the fall through above. */
387 rv
-= (TARGET_LARGE
? 4 : 2);
388 rv
-= cfun
->machine
->framesize_regs
;
389 case ARG_POINTER_REGNUM
:
398 /* Named Address Space support */
401 /* Return the appropriate mode for a named address pointer. */
402 #undef TARGET_ADDR_SPACE_POINTER_MODE
403 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
404 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
405 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
408 msp430_addr_space_pointer_mode (addr_space_t addrspace
)
413 case ADDR_SPACE_GENERIC
:
415 case ADDR_SPACE_NEAR
:
422 /* Function pointers are stored in unwind_word sized
423 variables, so make sure that unwind_word is big enough. */
424 #undef TARGET_UNWIND_WORD_MODE
425 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
428 msp430_unwind_word_mode (void)
430 return TARGET_LARGE
? PSImode
: HImode
;
433 /* Determine if one named address space is a subset of another. */
434 #undef TARGET_ADDR_SPACE_SUBSET_P
435 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
437 msp430_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
439 if (subset
== superset
)
442 return (subset
!= ADDR_SPACE_FAR
&& superset
== ADDR_SPACE_FAR
);
445 #undef TARGET_ADDR_SPACE_CONVERT
446 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
447 /* Convert from one address space to another. */
449 msp430_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
451 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
452 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
455 if (to_as
!= ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_FAR
)
457 /* This is unpredictable, as we're truncating off usable address
461 return gen_rtx_CONST (HImode
, op
);
463 result
= gen_reg_rtx (HImode
);
464 emit_insn (gen_truncpsihi2 (result
, op
));
467 else if (to_as
== ADDR_SPACE_FAR
&& from_as
!= ADDR_SPACE_FAR
)
469 /* This always works. */
472 return gen_rtx_CONST (PSImode
, op
);
474 result
= gen_reg_rtx (PSImode
);
475 emit_insn (gen_zero_extendhipsi2 (result
, op
));
482 /* Stack Layout and Calling Conventions. */
484 /* For each function, we list the gcc version and the TI version on
485 each line, where we're converting the function names. */
486 static char const * const special_convention_function_names
[] =
488 "__muldi3", "__mspabi_mpyll",
489 "__udivdi3", "__mspabi_divull",
490 "__umoddi3", "__mspabi_remull",
491 "__divdi3", "__mspabi_divlli",
492 "__moddi3", "__mspabi_remlli",
496 "__adddf3", "__mspabi_addd",
497 "__subdf3", "__mspabi_subd",
498 "__muldf3", "__mspabi_mpyd",
499 "__divdf3", "__mspabi_divd",
504 /* TRUE if the function passed is a "speical" function. Special
505 functions pass two DImode parameters in registers. */
507 msp430_special_register_convention_p (const char *name
)
511 for (i
= 0; special_convention_function_names
[i
]; i
++)
512 if (! strcmp (name
, special_convention_function_names
[i
]))
518 #undef TARGET_FUNCTION_VALUE_REGNO_P
519 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
522 msp430_function_value_regno_p (unsigned int regno
)
528 #undef TARGET_FUNCTION_VALUE
529 #define TARGET_FUNCTION_VALUE msp430_function_value
532 msp430_function_value (const_tree ret_type
,
533 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
534 bool outgoing ATTRIBUTE_UNUSED
)
536 return gen_rtx_REG (TYPE_MODE (ret_type
), 12);
539 #undef TARGET_LIBCALL_VALUE
540 #define TARGET_LIBCALL_VALUE msp430_libcall_value
543 msp430_libcall_value (machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
545 return gen_rtx_REG (mode
, 12);
548 /* Implements INIT_CUMULATIVE_ARGS. */
550 msp430_init_cumulative_args (CUMULATIVE_ARGS
*ca
,
551 tree fntype ATTRIBUTE_UNUSED
,
552 rtx libname ATTRIBUTE_UNUSED
,
553 tree fndecl ATTRIBUTE_UNUSED
,
554 int n_named_args ATTRIBUTE_UNUSED
)
557 memset (ca
, 0, sizeof(*ca
));
562 fname
= IDENTIFIER_POINTER (DECL_NAME (fndecl
));
564 fname
= XSTR (libname
, 0);
568 if (fname
&& msp430_special_register_convention_p (fname
))
572 /* Helper function for argument passing; this function is the common
573 code that determines where an argument will be passed. */
575 msp430_evaluate_arg (cumulative_args_t cap
,
577 const_tree type ATTRIBUTE_UNUSED
,
580 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
581 int nregs
= GET_MODE_SIZE (mode
);
593 nregs
= (nregs
+ 1) / 2;
597 /* Function is passed two DImode operands, in R8:R11 and
607 for (i
= 0; i
< 4; i
++)
608 if (! ca
->reg_used
[i
])
611 ca
->start_reg
= CA_FIRST_REG
+ i
;
616 for (i
= 0; i
< 3; i
++)
617 if (! ca
->reg_used
[i
] && ! ca
->reg_used
[i
+ 1])
620 ca
->start_reg
= CA_FIRST_REG
+ i
;
623 if (! ca
->reg_used
[3] && ca
->can_split
)
627 ca
->start_reg
= CA_FIRST_REG
+ 3;
634 if (! ca
->reg_used
[0]
635 && ! ca
->reg_used
[1]
636 && ! ca
->reg_used
[2]
637 && ! ca
->reg_used
[3])
640 ca
->start_reg
= CA_FIRST_REG
;
647 #undef TARGET_PROMOTE_PROTOTYPES
648 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
651 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED
)
656 #undef TARGET_FUNCTION_ARG
657 #define TARGET_FUNCTION_ARG msp430_function_arg
660 msp430_function_arg (cumulative_args_t cap
,
665 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
667 msp430_evaluate_arg (cap
, mode
, type
, named
);
670 return gen_rtx_REG (mode
, ca
->start_reg
);
675 #undef TARGET_ARG_PARTIAL_BYTES
676 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
679 msp430_arg_partial_bytes (cumulative_args_t cap
,
684 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
686 msp430_evaluate_arg (cap
, mode
, type
, named
);
688 if (ca
->reg_count
&& ca
->mem_count
)
689 return ca
->reg_count
* UNITS_PER_WORD
;
694 #undef TARGET_PASS_BY_REFERENCE
695 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
698 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED
,
701 bool named ATTRIBUTE_UNUSED
)
703 return (mode
== BLKmode
704 || (type
&& TREE_CODE (type
) == RECORD_TYPE
)
705 || (type
&& TREE_CODE (type
) == UNION_TYPE
));
708 #undef TARGET_CALLEE_COPIES
709 #define TARGET_CALLEE_COPIES msp430_callee_copies
712 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED
,
713 machine_mode mode ATTRIBUTE_UNUSED
,
714 const_tree type ATTRIBUTE_UNUSED
,
715 bool named ATTRIBUTE_UNUSED
)
720 #undef TARGET_FUNCTION_ARG_ADVANCE
721 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
724 msp430_function_arg_advance (cumulative_args_t cap
,
729 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
732 msp430_evaluate_arg (cap
, mode
, type
, named
);
734 if (ca
->start_reg
>= CA_FIRST_REG
)
735 for (i
= 0; i
< ca
->reg_count
; i
++)
736 ca
->reg_used
[i
+ ca
->start_reg
- CA_FIRST_REG
] = 1;
741 #undef TARGET_FUNCTION_ARG_BOUNDARY
742 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
745 msp430_function_arg_boundary (machine_mode mode
, const_tree type
)
748 && int_size_in_bytes (type
) > 1)
750 if (GET_MODE_BITSIZE (mode
) > 8)
755 #undef TARGET_RETURN_IN_MEMORY
756 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
759 msp430_return_in_memory (const_tree ret_type
, const_tree fntype ATTRIBUTE_UNUSED
)
761 machine_mode mode
= TYPE_MODE (ret_type
);
764 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == RECORD_TYPE
)
765 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == UNION_TYPE
))
768 if (GET_MODE_SIZE (mode
) > 8)
774 #undef TARGET_GET_RAW_ARG_MODE
775 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
778 msp430_get_raw_arg_mode (int regno
)
780 return (regno
== ARG_POINTER_REGNUM
) ? VOIDmode
: Pmode
;
783 #undef TARGET_GET_RAW_RESULT_MODE
784 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
787 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED
)
792 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
793 #define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
795 #include "gimplify.h"
796 #include "gimple-expr.h"
799 msp430_gimplify_va_arg_expr (tree valist
, tree type
, gimple_seq
*pre_p
,
802 tree addr
, t
, type_size
, rounded_size
, valist_tmp
;
803 unsigned HOST_WIDE_INT align
, boundary
;
806 indirect
= pass_by_reference (NULL
, TYPE_MODE (type
), type
, false);
808 type
= build_pointer_type (type
);
810 align
= PARM_BOUNDARY
/ BITS_PER_UNIT
;
811 boundary
= targetm
.calls
.function_arg_boundary (TYPE_MODE (type
), type
);
813 /* When we align parameter on stack for caller, if the parameter
814 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
815 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
817 if (boundary
> MAX_SUPPORTED_STACK_ALIGNMENT
)
818 boundary
= MAX_SUPPORTED_STACK_ALIGNMENT
;
820 boundary
/= BITS_PER_UNIT
;
822 /* Hoist the valist value into a temporary for the moment. */
823 valist_tmp
= get_initialized_tmp_var (valist
, pre_p
, NULL
);
825 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
826 requires greater alignment, we must perform dynamic alignment. */
828 && !integer_zerop (TYPE_SIZE (type
)))
830 /* FIXME: This is where this function diverts from targhooks.c:
831 std_gimplify_va_arg_expr(). It works, but I do not know why... */
832 if (! POINTER_TYPE_P (type
))
834 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
835 fold_build_pointer_plus_hwi (valist_tmp
, boundary
- 1));
836 gimplify_and_add (t
, pre_p
);
838 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
839 fold_build2 (BIT_AND_EXPR
, TREE_TYPE (valist
),
841 build_int_cst (TREE_TYPE (valist
), -boundary
)));
842 gimplify_and_add (t
, pre_p
);
848 /* If the actual alignment is less than the alignment of the type,
849 adjust the type accordingly so that we don't assume strict alignment
850 when dereferencing the pointer. */
851 boundary
*= BITS_PER_UNIT
;
852 if (boundary
< TYPE_ALIGN (type
))
854 type
= build_variant_type_copy (type
);
855 TYPE_ALIGN (type
) = boundary
;
858 /* Compute the rounded size of the type. */
859 type_size
= size_in_bytes (type
);
860 rounded_size
= round_up (type_size
, align
);
862 /* Reduce rounded_size so it's sharable with the postqueue. */
863 gimplify_expr (&rounded_size
, pre_p
, post_p
, is_gimple_val
, fb_rvalue
);
868 /* Compute new value for AP. */
869 t
= fold_build_pointer_plus (valist_tmp
, rounded_size
);
870 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist
, t
);
871 gimplify_and_add (t
, pre_p
);
873 addr
= fold_convert (build_pointer_type (type
), addr
);
876 addr
= build_va_arg_indirect_ref (addr
);
878 addr
= build_va_arg_indirect_ref (addr
);
883 /* Addressing Modes */
885 #undef TARGET_LEGITIMATE_ADDRESS_P
886 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
889 reg_ok_for_addr (rtx r
, bool strict
)
893 if (strict
&& rn
>= FIRST_PSEUDO_REGISTER
)
894 rn
= reg_renumber
[rn
];
895 if (strict
&& 0 <= rn
&& rn
< FIRST_PSEUDO_REGISTER
)
903 msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED
,
904 rtx x ATTRIBUTE_UNUSED
,
905 bool strict ATTRIBUTE_UNUSED
)
907 switch (GET_CODE (x
))
913 if (REG_P (XEXP (x
, 0)))
915 if (GET_MODE (x
) != GET_MODE (XEXP (x
, 0)))
917 if (!reg_ok_for_addr (XEXP (x
, 0), strict
))
919 switch (GET_CODE (XEXP (x
, 1)))
932 if (!reg_ok_for_addr (x
, strict
))
945 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
946 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
949 msp430_addr_space_legitimate_address_p (machine_mode mode
,
952 addr_space_t as ATTRIBUTE_UNUSED
)
954 return msp430_legitimate_address_p (mode
, x
, strict
);
957 #undef TARGET_ASM_INTEGER
958 #define TARGET_ASM_INTEGER msp430_asm_integer
960 msp430_asm_integer (rtx x
, unsigned int size
, int aligned_p
)
962 int c
= GET_CODE (x
);
964 if (size
== 3 && GET_MODE (x
) == PSImode
)
970 if (c
== SYMBOL_REF
|| c
== CONST
|| c
== LABEL_REF
|| c
== CONST_INT
)
972 fprintf (asm_out_file
, "\t.long\t");
973 output_addr_const (asm_out_file
, x
);
974 fputc ('\n', asm_out_file
);
979 return default_assemble_integer (x
, size
, aligned_p
);
982 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
983 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra
985 msp430_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED
, rtx x
)
991 #undef TARGET_LEGITIMATE_CONSTANT_P
992 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
995 msp430_legitimate_constant (machine_mode mode
, rtx x
)
997 return ! CONST_INT_P (x
)
999 /* GCC does not know the width of the PSImode, so make
1000 sure that it does not try to use a constant value that
1002 || (INTVAL (x
) < (1 << 20) && INTVAL (x
) >= (-1 << 20));
1006 #undef TARGET_RTX_COSTS
1007 #define TARGET_RTX_COSTS msp430_rtx_costs
1009 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED
,
1011 int outer_code ATTRIBUTE_UNUSED
,
1012 int opno ATTRIBUTE_UNUSED
,
1014 bool speed ATTRIBUTE_UNUSED
)
1019 if (GET_MODE (x
) == SImode
&& outer_code
== SET
)
1021 *total
= COSTS_N_INSNS (4);
1030 *total
= COSTS_N_INSNS (100);
1038 /* Function Entry and Exit */
1040 /* The MSP430 call frame looks like this:
1043 +--------------------+
1047 +--------------------+ <-- "arg pointer"
1049 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
1051 +--------------------+
1052 | SR if this func has|
1053 | been called via an |
1055 +--------------------+ <-- SP before prologue, also AP
1057 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
1059 +--------------------+ <-- "frame pointer"
1063 +--------------------+
1067 +--------------------+ <-- SP during function
1072 /* We use this to wrap all emitted insns in the prologue, so they get
1073 the "frame-related" (/f) flag set. */
1077 RTX_FRAME_RELATED_P (x
) = 1;
1081 /* This is the one spot that decides if a register is to be saved and
1082 restored in the prologue/epilogue. */
1084 msp430_preserve_reg_p (int regno
)
1086 /* PC, SP, SR, and the constant generator. */
1090 /* FIXME: add interrupt, EH, etc. */
1091 if (crtl
->calls_eh_return
)
1094 /* Shouldn't be more than the above, but just in case... */
1095 if (fixed_regs
[regno
])
1098 /* Interrupt handlers save all registers they use, even
1099 ones which are call saved. If they call other functions
1100 then *every* register is saved. */
1101 if (msp430_is_interrupt_func ())
1102 return ! crtl
->is_leaf
|| df_regs_ever_live_p (regno
);
1104 if (!call_used_regs
[regno
]
1105 && df_regs_ever_live_p (regno
))
1111 /* Compute all the frame-related fields in our machine_function
1114 msp430_compute_frame_info (void)
1118 cfun
->machine
->computed
= 1;
1119 cfun
->machine
->framesize_regs
= 0;
1120 cfun
->machine
->framesize_locals
= get_frame_size ();
1121 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
1123 for (i
= 0; i
< ARG_POINTER_REGNUM
; i
++)
1124 if (msp430_preserve_reg_p (i
))
1126 cfun
->machine
->need_to_save
[i
] = 1;
1127 cfun
->machine
->framesize_regs
+= (TARGET_LARGE
? 4 : 2);
1130 cfun
->machine
->need_to_save
[i
] = 0;
1132 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
1133 cfun
->machine
->framesize_locals
++;
1135 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
1136 + cfun
->machine
->framesize_locals
1137 + cfun
->machine
->framesize_outgoing
);
1141 is_attr_func (const char * attr
)
1143 return lookup_attribute (attr
, DECL_ATTRIBUTES (current_function_decl
)) != NULL_TREE
;
1146 /* Returns true if the current function has the "interrupt" attribute. */
1149 msp430_is_interrupt_func (void)
1151 if (current_function_decl
== NULL
)
1153 return is_attr_func ("interrupt");
1157 is_wakeup_func (void)
1159 return msp430_is_interrupt_func () && is_attr_func ("wakeup");
1163 is_naked_func (void)
1165 return is_attr_func ("naked");
1169 is_reentrant_func (void)
1171 return is_attr_func ("reentrant");
1175 is_critical_func (void)
1177 return is_attr_func ("critical");
1180 #undef TARGET_ASM_FUNCTION_PROLOGUE
1181 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
1184 msp430_start_function (FILE *outfile
, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED
)
1188 fprintf (outfile
, "; start of function\n");
1190 if (DECL_ATTRIBUTES (current_function_decl
) != NULL_TREE
)
1192 fprintf (outfile
, "; attributes: ");
1193 if (is_naked_func ())
1194 fprintf (outfile
, "naked ");
1195 if (msp430_is_interrupt_func ())
1196 fprintf (outfile
, "interrupt ");
1197 if (is_reentrant_func ())
1198 fprintf (outfile
, "reentrant ");
1199 if (is_critical_func ())
1200 fprintf (outfile
, "critical ");
1201 if (is_wakeup_func ())
1202 fprintf (outfile
, "wakeup ");
1203 fprintf (outfile
, "\n");
1206 fprintf (outfile
, "; framesize_regs: %d\n", cfun
->machine
->framesize_regs
);
1207 fprintf (outfile
, "; framesize_locals: %d\n", cfun
->machine
->framesize_locals
);
1208 fprintf (outfile
, "; framesize_outgoing: %d\n", cfun
->machine
->framesize_outgoing
);
1209 fprintf (outfile
, "; framesize: %d\n", cfun
->machine
->framesize
);
1210 fprintf (outfile
, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, FRAME_POINTER_REGNUM
));
1211 fprintf (outfile
, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM
, STACK_POINTER_REGNUM
));
1214 fprintf (outfile
, "; saved regs:");
1215 for (r
= 0; r
< ARG_POINTER_REGNUM
; r
++)
1216 if (cfun
->machine
->need_to_save
[r
])
1218 fprintf (outfile
, " %s", reg_names
[r
]);
1222 fprintf (outfile
, "(none)");
1223 fprintf (outfile
, "\n");
1226 /* Common code to change the stack pointer. */
1228 increment_stack (HOST_WIDE_INT amount
)
1231 rtx sp
= stack_pointer_rtx
;
1238 inc
= GEN_INT (- amount
);
1240 F (emit_insn (gen_subpsi3 (sp
, sp
, inc
)));
1242 F (emit_insn (gen_subhi3 (sp
, sp
, inc
)));
1246 inc
= GEN_INT (amount
);
1248 emit_insn (gen_addpsi3 (sp
, sp
, inc
));
1250 emit_insn (gen_addhi3 (sp
, sp
, inc
));
1254 /* Verify MSP430 specific attributes. */
1257 msp430_attr (tree
* node
,
1260 int flags ATTRIBUTE_UNUSED
,
1261 bool * no_add_attrs
)
1263 gcc_assert (DECL_P (* node
));
1267 tree value
= TREE_VALUE (args
);
1269 switch (TREE_CODE (value
))
1272 if ( strcmp (TREE_STRING_POINTER (value
), "reset")
1273 && strcmp (TREE_STRING_POINTER (value
), "nmi")
1274 && strcmp (TREE_STRING_POINTER (value
), "watchdog"))
1275 /* Allow the attribute to be added - the linker script
1276 being used may still recognise this name. */
1277 warning (OPT_Wattributes
,
1278 "unrecognised interrupt vector argument of %qE attribute",
1283 if (wi::gtu_p (value
, 63))
1284 /* Allow the attribute to be added - the linker script
1285 being used may still recognise this value. */
1286 warning (OPT_Wattributes
,
1287 "numeric argument of %qE attribute must be in range 0..63",
1292 warning (OPT_Wattributes
,
1293 "argument of %qE attribute is not a string constant or number",
1295 *no_add_attrs
= true;
1300 if (TREE_CODE (* node
) != FUNCTION_DECL
)
1302 warning (OPT_Wattributes
,
1303 "%qE attribute only applies to functions",
1305 * no_add_attrs
= true;
1308 /* FIXME: We ought to check that the interrupt handler
1309 attribute has been applied to a void function. */
1310 /* FIXME: We should check that reentrant and critical
1311 functions are not naked and that critical functions
1312 are not reentrant. */
1317 #undef TARGET_ATTRIBUTE_TABLE
1318 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
1320 /* Table of MSP430-specific attributes. */
1321 const struct attribute_spec msp430_attribute_table
[] =
1323 /* Name min_len decl_req, fn_type_req, affects_type_identity
1324 max_len, type_req, handler. */
1325 { "interrupt", 0, 1, true, false, false, msp430_attr
, false },
1326 { "naked", 0, 0, true, false, false, msp430_attr
, false },
1327 { "reentrant", 0, 0, true, false, false, msp430_attr
, false },
1328 { "critical", 0, 0, true, false, false, msp430_attr
, false },
1329 { "wakeup", 0, 0, true, false, false, msp430_attr
, false },
1330 { NULL
, 0, 0, false, false, false, NULL
, false }
1334 msp430_start_function (FILE *file
, const char *name
, tree decl
)
1338 int_attr
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl
));
1339 if (int_attr
!= NULL_TREE
)
1341 tree intr_vector
= TREE_VALUE (int_attr
);
1343 if (intr_vector
!= NULL_TREE
)
1347 intr_vector
= TREE_VALUE (intr_vector
);
1349 /* The interrupt attribute has a vector value. Turn this into a
1350 section name, switch to that section and put the address of
1351 the current function into that vector slot. Note msp430_attr()
1352 has already verified the vector name for us. */
1353 if (TREE_CODE (intr_vector
) == STRING_CST
)
1354 sprintf (buf
, "__interrupt_vector_%.80s",
1355 TREE_STRING_POINTER (intr_vector
));
1356 else /* TREE_CODE (intr_vector) == INTEGER_CST */
1357 sprintf (buf
, "__interrupt_vector_%u",
1358 (unsigned int) TREE_INT_CST_LOW (intr_vector
));
1360 switch_to_section (get_section (buf
, SECTION_CODE
, decl
));
1361 fputs ("\t.word\t", file
);
1362 assemble_name (file
, name
);
1368 switch_to_section (function_section (decl
));
1369 ASM_OUTPUT_FUNCTION_LABEL (file
, name
, decl
);
1373 msp430_function_section (tree decl
, enum node_frequency freq
, bool startup
, bool exit
)
1375 /* In large mode we must make sure that interrupt handlers are put into
1376 low memory as the vector table only accepts 16-bit addresses. */
1378 && lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl
)))
1379 return get_section (".lowtext", SECTION_CODE
| SECTION_WRITE
, decl
);
1381 /* Otherwise, use the default function section. */
1382 return default_function_section (decl
, freq
, startup
, exit
);
1385 #undef TARGET_ASM_FUNCTION_SECTION
1386 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
1390 MSP430_BUILTIN_BIC_SR
,
1391 MSP430_BUILTIN_BIS_SR
,
1392 MSP430_BUILTIN_DELAY_CYCLES
,
1396 static GTY(()) tree msp430_builtins
[(int) MSP430_BUILTIN_max
];
1399 msp430_init_builtins (void)
1401 tree void_ftype_int
= build_function_type_list (void_type_node
, integer_type_node
, NULL
);
1402 tree void_ftype_longlong
= build_function_type_list (void_type_node
, long_long_integer_type_node
, NULL
);
1404 msp430_builtins
[MSP430_BUILTIN_BIC_SR
] =
1405 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int
,
1406 MSP430_BUILTIN_BIC_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
1408 msp430_builtins
[MSP430_BUILTIN_BIS_SR
] =
1409 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int
,
1410 MSP430_BUILTIN_BIS_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
1412 msp430_builtins
[MSP430_BUILTIN_DELAY_CYCLES
] =
1413 add_builtin_function ( "__delay_cycles", void_ftype_longlong
,
1414 MSP430_BUILTIN_DELAY_CYCLES
, BUILT_IN_MD
, NULL
, NULL_TREE
);
1418 msp430_builtin_decl (unsigned code
, bool initialize ATTRIBUTE_UNUSED
)
1422 case MSP430_BUILTIN_BIC_SR
:
1423 case MSP430_BUILTIN_BIS_SR
:
1424 case MSP430_BUILTIN_DELAY_CYCLES
:
1425 return msp430_builtins
[code
];
1427 return error_mark_node
;
1431 /* These constants are really register reads, which are faster than
1432 regular constants. */
1434 cg_magic_constant (HOST_WIDE_INT c
)
1452 msp430_expand_delay_cycles (rtx arg
)
1454 HOST_WIDE_INT i
, c
, n
;
1455 /* extra cycles for MSP430X instructions */
1456 #define CYCX(M,X) (msp430x ? (X) : (M))
1458 if (GET_CODE (arg
) != CONST_INT
)
1460 error ("__delay_cycles() only takes constant arguments");
1466 if (HOST_BITS_PER_WIDE_INT
> 32)
1470 error ("__delay_cycles only takes non-negative cycle counts.");
1475 emit_insn (gen_delay_cycles_start (arg
));
1477 /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
1478 if (c
> 3 * 0xffff + CYCX (7, 10))
1481 /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
1482 if (c
>= 0x10000 * 7 + CYCX (14, 16))
1485 c
-= CYCX (14, 16) + 7 * 0x10000;
1488 if ((unsigned long long) i
> 0xffffffffULL
)
1490 error ("__delay_cycles is limited to 32-bit loop counts.");
1496 i
= (c
- CYCX (14, 16)) / 7;
1497 c
-= CYCX (14, 16) + i
* 7;
1500 if (cg_magic_constant (i
& 0xffff))
1502 if (cg_magic_constant ((i
>> 16) & 0xffff))
1506 emit_insn (gen_delay_cycles_32x (GEN_INT (i
), GEN_INT (n
- c
)));
1508 emit_insn (gen_delay_cycles_32 (GEN_INT (i
), GEN_INT (n
- c
)));
1511 /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
1515 i
= (c
- CYCX (7, 10)) / 3;
1516 c
-= CYCX (7, 10) + i
* 3;
1518 if (cg_magic_constant (i
))
1522 emit_insn (gen_delay_cycles_16x (GEN_INT (i
), GEN_INT (n
- c
)));
1524 emit_insn (gen_delay_cycles_16 (GEN_INT (i
), GEN_INT (n
- c
)));
1529 emit_insn (gen_delay_cycles_2 ());
1535 emit_insn (gen_delay_cycles_1 ());
1539 emit_insn (gen_delay_cycles_end (arg
));
1545 msp430_expand_builtin (tree exp
,
1546 rtx target ATTRIBUTE_UNUSED
,
1547 rtx subtarget ATTRIBUTE_UNUSED
,
1548 machine_mode mode ATTRIBUTE_UNUSED
,
1549 int ignore ATTRIBUTE_UNUSED
)
1551 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
1552 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
1553 rtx arg1
= expand_normal (CALL_EXPR_ARG (exp
, 0));
1555 if (fcode
== MSP430_BUILTIN_DELAY_CYCLES
)
1556 return msp430_expand_delay_cycles (arg1
);
1558 if (! msp430_is_interrupt_func ())
1560 error ("MSP430 builtin functions only work inside interrupt handlers");
1564 if (! REG_P (arg1
) && ! CONSTANT_P (arg1
))
1565 arg1
= force_reg (mode
, arg1
);
1569 case MSP430_BUILTIN_BIC_SR
: emit_insn (gen_bic_SR (arg1
)); break;
1570 case MSP430_BUILTIN_BIS_SR
: emit_insn (gen_bis_SR (arg1
)); break;
1572 internal_error ("bad builtin code");
1578 #undef TARGET_INIT_BUILTINS
1579 #define TARGET_INIT_BUILTINS msp430_init_builtins
1581 #undef TARGET_EXPAND_BUILTIN
1582 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
1584 #undef TARGET_BUILTIN_DECL
1585 #define TARGET_BUILTIN_DECL msp430_builtin_decl
1588 msp430_expand_prologue (void)
1592 /* Always use stack_pointer_rtx instead of calling
1593 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
1594 that there is a single rtx representing the stack pointer,
1595 namely stack_pointer_rtx, and uses == to recognize it. */
1596 rtx sp
= stack_pointer_rtx
;
1599 if (is_naked_func ())
1601 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
1602 examines the output of the gen_prologue() function. */
1603 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
1607 emit_insn (gen_prologue_start_marker ());
1609 if (is_critical_func ())
1611 emit_insn (gen_push_intr_state ());
1612 emit_insn (gen_disable_interrupts ());
1614 else if (is_reentrant_func ())
1615 emit_insn (gen_disable_interrupts ());
1617 if (!cfun
->machine
->computed
)
1618 msp430_compute_frame_info ();
1620 if (flag_stack_usage_info
)
1621 current_function_static_stack_size
= cfun
->machine
->framesize
;
1623 if (crtl
->args
.pretend_args_size
)
1627 gcc_assert (crtl
->args
.pretend_args_size
== 2);
1629 p
= emit_insn (gen_grow_and_swap ());
1631 /* Document the stack decrement... */
1632 note
= F (gen_rtx_SET (Pmode
, stack_pointer_rtx
,
1633 gen_rtx_MINUS (Pmode
, stack_pointer_rtx
, GEN_INT (2))));
1634 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
1636 /* ...and the establishment of a new location for the return address. */
1637 note
= F (gen_rtx_SET (Pmode
, gen_rtx_MEM (Pmode
,
1638 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, GEN_INT (-2))),
1640 add_reg_note (p
, REG_CFA_OFFSET
, note
);
1644 for (i
= 15; i
>= 4; i
--)
1645 if (cfun
->machine
->need_to_save
[i
])
1650 for (seq
= i
- 1; seq
>= 4 && cfun
->machine
->need_to_save
[seq
]; seq
--)
1656 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
1657 p
= F (emit_insn (gen_pushm (gen_rtx_REG (Pmode
, i
),
1660 note
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (count
+ 1));
1662 XVECEXP (note
, 0, 0)
1663 = F (gen_rtx_SET (VOIDmode
,
1665 gen_rtx_PLUS (Pmode
,
1667 GEN_INT (count
* (TARGET_LARGE
? -4 : -2)))));
1669 /* *sp-- = R[i-j] */
1673 for (j
= 0; j
< count
; j
++)
1676 int ofs
= (count
- j
- 1) * (TARGET_LARGE
? 4 : 2);
1679 addr
= gen_rtx_PLUS (Pmode
, sp
, GEN_INT (ofs
));
1681 addr
= stack_pointer_rtx
;
1683 XVECEXP (note
, 0, j
+ 1) =
1684 F (gen_rtx_SET (VOIDmode
,
1685 gen_rtx_MEM (Pmode
, addr
),
1686 gen_rtx_REG (Pmode
, i
- j
)) );
1689 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
1693 F (emit_insn (gen_push (gen_rtx_REG (Pmode
, i
))));
1696 if (frame_pointer_needed
)
1697 F (emit_move_insn (gen_rtx_REG (Pmode
, FRAME_POINTER_REGNUM
), sp
));
1699 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1701 increment_stack (- fs
);
1703 emit_insn (gen_prologue_end_marker ());
1707 msp430_expand_epilogue (int is_eh
)
1713 if (is_naked_func ())
1715 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
1716 examines the output of the gen_epilogue() function. */
1717 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
1721 if (cfun
->machine
->need_to_save
[10])
1723 /* Check for a helper function. */
1724 helper_n
= 7; /* For when the loop below never sees a match. */
1725 for (i
= 9; i
>= 4; i
--)
1726 if (!cfun
->machine
->need_to_save
[i
])
1730 if (cfun
->machine
->need_to_save
[i
])
1739 emit_insn (gen_epilogue_start_marker ());
1741 if (cfun
->decl
&& strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun
->decl
)), "main") == 0)
1742 emit_insn (gen_msp430_refsym_need_exit ());
1744 if (is_wakeup_func ())
1745 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
1746 status register current residing on the stack. When this function
1747 executes its RETI instruction the SR will be updated with this saved
1748 value, thus ensuring that the processor is woken up from any low power
1749 state in which it may be residing. */
1750 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
1752 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1754 increment_stack (fs
);
1758 /* We need to add the right "SP" register save just after the
1759 regular ones, so that when we pop it off we're in the EH
1760 return frame, not this one. This overwrites our own return
1761 address, but we're not going to be returning anyway. */
1762 rtx r12
= gen_rtx_REG (Pmode
, 12);
1763 rtx (*addPmode
)(rtx
, rtx
, rtx
) = TARGET_LARGE
? gen_addpsi3
: gen_addhi3
;
1765 /* R12 will hold the new SP. */
1766 i
= cfun
->machine
->framesize_regs
;
1767 emit_move_insn (r12
, stack_pointer_rtx
);
1768 emit_insn (addPmode (r12
, r12
, EH_RETURN_STACKADJ_RTX
));
1769 emit_insn (addPmode (r12
, r12
, GEN_INT (i
)));
1770 emit_move_insn (gen_rtx_MEM (Pmode
, plus_constant (Pmode
, stack_pointer_rtx
, i
)), r12
);
1773 for (i
= 4; i
<= 15; i
++)
1774 if (cfun
->machine
->need_to_save
[i
])
1778 for (seq
= i
+ 1; seq
<= 15 && cfun
->machine
->need_to_save
[seq
]; seq
++)
1784 /* Note: With TARGET_LARGE we still use
1785 POPM as POPX.A is two bytes bigger. */
1786 emit_insn (gen_popm (stack_pointer_rtx
, GEN_INT (seq
- 1),
1790 else if (i
== 11 - helper_n
1791 && ! msp430_is_interrupt_func ()
1792 && ! is_reentrant_func ()
1793 && ! is_critical_func ()
1794 && crtl
->args
.pretend_args_size
== 0
1795 /* Calling the helper takes as many bytes as the POP;RET sequence. */
1799 emit_insn (gen_epilogue_helper (GEN_INT (helper_n
)));
1803 emit_insn (gen_pop (gen_rtx_REG (Pmode
, i
)));
1808 /* Also pop SP, which puts us into the EH return frame. Except
1809 that you can't "pop" sp, you have to just load it off the
1811 emit_move_insn (stack_pointer_rtx
, gen_rtx_MEM (Pmode
, stack_pointer_rtx
));
1814 if (crtl
->args
.pretend_args_size
)
1815 emit_insn (gen_swap_and_shrink ());
1817 if (is_critical_func ())
1818 emit_insn (gen_pop_intr_state ());
1819 else if (is_reentrant_func ())
1820 emit_insn (gen_enable_interrupts ());
1822 emit_jump_insn (gen_msp_return ());
1825 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
1826 m32c_emit_eh_epilogue. */
1828 msp430_eh_return_stackadj_rtx (void)
1830 if (!cfun
->machine
->eh_stack_adjust
)
1834 sa
= gen_rtx_REG (Pmode
, 15);
1835 cfun
->machine
->eh_stack_adjust
= sa
;
1837 return cfun
->machine
->eh_stack_adjust
;
1840 /* This function is called before reload, to "fix" the stack in
1841 preparation for an EH return. */
1843 msp430_expand_eh_return (rtx eh_handler
)
1845 /* These are all Pmode */
1846 rtx ap
, sa
, ra
, tmp
;
1848 ap
= arg_pointer_rtx
;
1849 sa
= msp430_eh_return_stackadj_rtx ();
1853 tmp
= gen_rtx_PLUS (Pmode
, ap
, sa
);
1854 tmp
= plus_constant (Pmode
, tmp
, TARGET_LARGE
? -4 : -2);
1855 tmp
= gen_rtx_MEM (Pmode
, tmp
);
1856 emit_move_insn (tmp
, ra
);
1859 #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
1860 #define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
1862 msp430_init_dwarf_reg_sizes_extra (tree address
)
1865 rtx addr
= expand_normal (address
);
1866 rtx mem
= gen_rtx_MEM (BLKmode
, addr
);
1871 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1873 unsigned int dnum
= DWARF_FRAME_REGNUM (i
);
1874 unsigned int rnum
= DWARF2_FRAME_REG_OUT (dnum
, 1);
1876 if (rnum
< DWARF_FRAME_REGISTERS
)
1878 HOST_WIDE_INT offset
= rnum
* GET_MODE_SIZE (QImode
);
1880 emit_move_insn (adjust_address (mem
, QImode
, offset
),
1881 gen_int_mode (4, QImode
));
1886 /* This is a list of MD patterns that implement fixed-count shifts. */
1892 rtx (*genfunc
)(rtx
,rtx
);
1894 const_shift_helpers
[] =
1896 #define CSH(N,C,X,G) { "__mspabi_"N, C, X, gen_##G }
1898 CSH ("slli", 1, 1, slli_1
),
1899 CSH ("slll", 1, 1, slll_1
),
1900 CSH ("slll", 2, 1, slll_2
),
1902 CSH ("srai", 1, 0, srai_1
),
1903 CSH ("sral", 1, 0, sral_1
),
1904 CSH ("sral", 2, 0, sral_2
),
1906 CSH ("srll", 1, 0, srll_1
),
1907 CSH ("srll", 2, 1, srll_2x
),
1912 /* The MSP430 ABI defines a number of helper functions that should be
1913 used for, for example, 32-bit shifts. This function is called to
1914 emit such a function, using the table above to optimize some
1917 msp430_expand_helper (rtx
*operands
, const char *helper_name
, bool const_variants
)
1920 char *helper_const
= NULL
;
1923 machine_mode arg0mode
= GET_MODE (operands
[0]);
1924 machine_mode arg1mode
= GET_MODE (operands
[1]);
1925 machine_mode arg2mode
= GET_MODE (operands
[2]);
1926 int have_430x
= msp430x
? 1 : 0;
1928 if (CONST_INT_P (operands
[2]))
1932 for (i
=0; const_shift_helpers
[i
].name
; i
++)
1934 if (const_shift_helpers
[i
].need_430x
<= have_430x
1935 && strcmp (helper_name
, const_shift_helpers
[i
].name
) == 0
1936 && INTVAL (operands
[2]) == const_shift_helpers
[i
].count
)
1938 emit_insn (const_shift_helpers
[i
].genfunc (operands
[0], operands
[1]));
1944 if (arg1mode
== VOIDmode
)
1945 arg1mode
= arg0mode
;
1946 if (arg2mode
== VOIDmode
)
1947 arg2mode
= arg0mode
;
1949 if (arg1mode
== SImode
)
1956 && CONST_INT_P (operands
[2])
1957 && INTVAL (operands
[2]) >= 1
1958 && INTVAL (operands
[2]) <= 15)
1960 /* Note that the INTVAL is limited in value and length by the conditional above. */
1961 int len
= strlen (helper_name
) + 4;
1962 helper_const
= (char *) xmalloc (len
);
1963 snprintf (helper_const
, len
, "%s_%d", helper_name
, (int) INTVAL (operands
[2]));
1966 emit_move_insn (gen_rtx_REG (arg1mode
, 12),
1969 emit_move_insn (gen_rtx_REG (arg2mode
, arg2
),
1972 c
= gen_call_value_internal (gen_rtx_REG (arg0mode
, 12),
1973 gen_rtx_SYMBOL_REF (VOIDmode
, helper_const
? helper_const
: helper_name
),
1975 c
= emit_call_insn (c
);
1976 RTL_CONST_CALL_P (c
) = 1;
1979 use_regs (&f
, 12, arg1sz
);
1981 use_regs (&f
, arg2
, 1);
1982 add_function_usage_to (c
, f
);
1984 emit_move_insn (operands
[0],
1985 gen_rtx_REG (arg0mode
, 12));
1988 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
1990 msp430_fixup_compare_operands (machine_mode my_mode
, rtx
* operands
)
1992 /* constants we're looking for, not constants which are allowed. */
1993 int const_op_idx
= 1;
1995 if (msp430_reversible_cmp_operator (operands
[0], VOIDmode
))
1998 if (GET_CODE (operands
[const_op_idx
]) != REG
1999 && GET_CODE (operands
[const_op_idx
]) != MEM
)
2000 operands
[const_op_idx
] = copy_to_mode_reg (my_mode
, operands
[const_op_idx
]);
2003 /* Simplify_gen_subreg() doesn't handle memory references the way we
2004 need it to below, so we use this function for when we must get a
2005 valid subreg in a "natural" state. */
2007 msp430_subreg (machine_mode mode
, rtx r
, machine_mode omode
, int byte
)
2011 if (GET_CODE (r
) == SUBREG
2012 && SUBREG_BYTE (r
) == 0)
2014 rtx ireg
= SUBREG_REG (r
);
2015 machine_mode imode
= GET_MODE (ireg
);
2017 /* special case for (HI (SI (PSI ...), 0)) */
2018 if (imode
== PSImode
2021 rv
= gen_rtx_SUBREG (mode
, ireg
, byte
);
2023 rv
= simplify_gen_subreg (mode
, ireg
, imode
, byte
);
2025 else if (GET_CODE (r
) == MEM
)
2026 rv
= adjust_address (r
, mode
, byte
);
2028 rv
= simplify_gen_subreg (mode
, r
, omode
, byte
);
2036 /* Called by movsi_x to generate the HImode operands. */
2038 msp430_split_movsi (rtx
*operands
)
2040 rtx op00
, op02
, op10
, op12
;
2042 op00
= msp430_subreg (HImode
, operands
[0], SImode
, 0);
2043 op02
= msp430_subreg (HImode
, operands
[0], SImode
, 2);
2045 if (GET_CODE (operands
[1]) == CONST
2046 || GET_CODE (operands
[1]) == SYMBOL_REF
)
2048 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
2049 op10
= gen_rtx_CONST (HImode
, op10
);
2050 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
2051 op12
= gen_rtx_CONST (HImode
, op12
);
2055 op10
= msp430_subreg (HImode
, operands
[1], SImode
, 0);
2056 op12
= msp430_subreg (HImode
, operands
[1], SImode
, 2);
2059 if (rtx_equal_p (operands
[0], operands
[1]))
2066 else if (rtx_equal_p (op00
, op12
)
2067 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
2068 || (REG_P (op00
) && reg_mentioned_p (op00
, op10
))
2069 /* Or storing (rN) into mem (rN). */
2070 || (REG_P (op10
) && reg_mentioned_p (op10
, op00
))
2088 /* The MSPABI specifies the names of various helper functions, many of
2089 which are compatible with GCC's helpers. This table maps the GCC
2090 name to the MSPABI name. */
2093 char const * const gcc_name
;
2094 char const * const ti_name
;
2096 helper_function_name_mappings
[] =
2098 /* Floating point to/from integer conversions. */
2099 { "__truncdfsf2", "__mspabi_cvtdf" },
2100 { "__extendsfdf2", "__mspabi_cvtfd" },
2101 { "__fixdfhi", "__mspabi_fixdi" },
2102 { "__fixdfsi", "__mspabi_fixdli" },
2103 { "__fixdfdi", "__mspabi_fixdlli" },
2104 { "__fixunsdfhi", "__mspabi_fixdu" },
2105 { "__fixunsdfsi", "__mspabi_fixdul" },
2106 { "__fixunsdfdi", "__mspabi_fixdull" },
2107 { "__fixsfhi", "__mspabi_fixfi" },
2108 { "__fixsfsi", "__mspabi_fixfli" },
2109 { "__fixsfdi", "__mspabi_fixflli" },
2110 { "__fixunsfhi", "__mspabi_fixfu" },
2111 { "__fixunsfsi", "__mspabi_fixful" },
2112 { "__fixunsfdi", "__mspabi_fixfull" },
2113 { "__floathisf", "__mspabi_fltif" },
2114 { "__floatsisf", "__mspabi_fltlif" },
2115 { "__floatdisf", "__mspabi_fltllif" },
2116 { "__floathidf", "__mspabi_fltid" },
2117 { "__floatsidf", "__mspabi_fltlid" },
2118 { "__floatdidf", "__mspabi_fltllid" },
2119 { "__floatunhisf", "__mspabi_fltuf" },
2120 { "__floatunsisf", "__mspabi_fltulf" },
2121 { "__floatundisf", "__mspabi_fltullf" },
2122 { "__floatunhidf", "__mspabi_fltud" },
2123 { "__floatunsidf", "__mspabi_fltuld" },
2124 { "__floatundidf", "__mspabi_fltulld" },
2126 /* Floating point comparisons. */
2127 /* GCC uses individual functions for each comparison, TI uses one
2128 compare <=> function. */
2130 /* Floating point arithmatic */
2131 { "__adddf3", "__mspabi_addd" },
2132 { "__addsf3", "__mspabi_addf" },
2133 { "__divdf3", "__mspabi_divd" },
2134 { "__divsf3", "__mspabi_divf" },
2135 { "__muldf3", "__mspabi_mpyd" },
2136 { "__mulsf3", "__mspabi_mpyf" },
2137 { "__subdf3", "__mspabi_subd" },
2138 { "__subsf3", "__mspabi_subf" },
2139 /* GCC does not use helper functions for negation */
2141 /* Integer multiply, divide, remainder. */
2142 { "__mulhi3", "__mspabi_mpyi" },
2143 { "__mulsi3", "__mspabi_mpyl" },
2144 { "__muldi3", "__mspabi_mpyll" },
2146 /* Clarify signed vs unsigned first. */
2147 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
2148 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
2151 { "__divhi3", "__mspabi_divi" },
2152 { "__divsi3", "__mspabi_divli" },
2153 { "__divdi3", "__mspabi_divlli" },
2154 { "__udivhi3", "__mspabi_divu" },
2155 { "__udivsi3", "__mspabi_divlu" },
2156 { "__udivdi3", "__mspabi_divllu" },
2157 { "__modhi3", "__mspabi_remi" },
2158 { "__modsi3", "__mspabi_remli" },
2159 { "__moddi3", "__mspabi_remlli" },
2160 { "__umodhi3", "__mspabi_remu" },
2161 { "__umodsi3", "__mspabi_remul" },
2162 { "__umoddi3", "__mspabi_remull" },
2164 /* Bitwise operations. */
2165 /* Rotation - no rotation support yet. */
2166 /* Logical left shift - gcc already does these itself. */
2167 /* Arithmetic left shift - gcc already does these itself. */
2168 /* Arithmetic right shift - gcc already does these itself. */
2173 /* Returns true if the current MCU supports an F5xxx series
2174 hardware multiper. */
2177 msp430_use_f5_series_hwmult (void)
2179 static const char * cached_match
= NULL
;
2180 static bool cached_result
;
2182 if (msp430_hwmult_type
== F5SERIES
)
2185 if (target_mcu
== NULL
|| msp430_hwmult_type
!= AUTO
)
2188 if (target_mcu
== cached_match
)
2189 return cached_result
;
2191 cached_match
= target_mcu
;
2193 if (strncasecmp (target_mcu
, "msp430f5", 8) == 0)
2194 return cached_result
= true;
2196 static const char * known_f5_mult_mcus
[] =
2198 "cc430f5123", "cc430f5125", "cc430f5133",
2199 "cc430f5135", "cc430f5137", "cc430f5143",
2200 "cc430f5145", "cc430f5147", "cc430f6125",
2201 "cc430f6126", "cc430f6127", "cc430f6135",
2202 "cc430f6137", "cc430f6143", "cc430f6145",
2203 "cc430f6147", "msp430bt5190", "msp430sl5438a"
2207 for (i
= ARRAY_SIZE (known_f5_mult_mcus
); i
--;)
2208 if (strcasecmp (target_mcu
, known_f5_mult_mcus
[i
]) == 0)
2209 return cached_result
= true;
2211 return cached_result
= false;
2214 /* Returns true if the current MCU has a second generation
2215 32-bit hardware multiplier. */
2218 use_32bit_hwmult (void)
2220 static const char * known_32bit_mult_mcus
[] =
2222 "msp430f4783", "msp430f4793", "msp430f4784",
2223 "msp430f4794", "msp430f47126", "msp430f47127",
2224 "msp430f47163", "msp430f47173", "msp430f47183",
2225 "msp430f47193", "msp430f47166", "msp430f47176",
2226 "msp430f47186", "msp430f47196", "msp430f47167",
2227 "msp430f47177", "msp430f47187", "msp430f47197"
2229 static const char * cached_match
= NULL
;
2230 static bool cached_result
;
2233 if (msp430_hwmult_type
== LARGE
)
2236 if (target_mcu
== NULL
|| msp430_hwmult_type
!= AUTO
)
2239 if (target_mcu
== cached_match
)
2240 return cached_result
;
2242 cached_match
= target_mcu
;
2243 for (i
= ARRAY_SIZE (known_32bit_mult_mcus
); i
--;)
2244 if (strcasecmp (target_mcu
, known_32bit_mult_mcus
[i
]) == 0)
2245 return cached_result
= true;
2247 return cached_result
= false;
2250 /* Returns true if the current MCU does not have a
2251 hardware multiplier of any kind. */
2254 msp430_no_hwmult (void)
2256 static const char * known_nomult_mcus
[] =
2258 "msp430c091", "msp430c092", "msp430c111",
2259 "msp430c1111", "msp430c112", "msp430c1121",
2260 "msp430c1331", "msp430c1351", "msp430c311s",
2261 "msp430c312", "msp430c313", "msp430c314",
2262 "msp430c315", "msp430c323", "msp430c325",
2263 "msp430c412", "msp430c413", "msp430e112",
2264 "msp430e313", "msp430e315", "msp430e325",
2265 "msp430f110", "msp430f1101", "msp430f1101a",
2266 "msp430f1111", "msp430f1111a", "msp430f112",
2267 "msp430f1121", "msp430f1121a", "msp430f1122",
2268 "msp430f1132", "msp430f122", "msp430f1222",
2269 "msp430f123", "msp430f1232", "msp430f133",
2270 "msp430f135", "msp430f155", "msp430f156",
2271 "msp430f157", "msp430f2001", "msp430f2002",
2272 "msp430f2003", "msp430f2011", "msp430f2012",
2273 "msp430f2013", "msp430f2101", "msp430f2111",
2274 "msp430f2112", "msp430f2121", "msp430f2122",
2275 "msp430f2131", "msp430f2132", "msp430f2232",
2276 "msp430f2234", "msp430f2252", "msp430f2254",
2277 "msp430f2272", "msp430f2274", "msp430f412",
2278 "msp430f413", "msp430f4132", "msp430f415",
2279 "msp430f4152", "msp430f417", "msp430f4250",
2280 "msp430f4260", "msp430f4270", "msp430f435",
2281 "msp430f4351", "msp430f436", "msp430f4361",
2282 "msp430f437", "msp430f4371", "msp430f438",
2283 "msp430f439", "msp430f477", "msp430f478",
2284 "msp430f479", "msp430fe423", "msp430fe4232",
2285 "msp430fe423a", "msp430fe4242", "msp430fe425",
2286 "msp430fe4252", "msp430fe425a", "msp430fe427",
2287 "msp430fe4272", "msp430fe427a", "msp430fg4250",
2288 "msp430fg4260", "msp430fg4270", "msp430fg437",
2289 "msp430fg438", "msp430fg439", "msp430fg477",
2290 "msp430fg478", "msp430fg479", "msp430fr2032",
2291 "msp430fr2033", "msp430fr4131", "msp430fr4132",
2292 "msp430fr4133", "msp430fw423", "msp430fw425",
2293 "msp430fw427", "msp430fw428", "msp430fw429",
2294 "msp430g2001", "msp430g2101", "msp430g2102",
2295 "msp430g2111", "msp430g2112", "msp430g2113",
2296 "msp430g2121", "msp430g2131", "msp430g2132",
2297 "msp430g2152", "msp430g2153", "msp430g2201",
2298 "msp430g2202", "msp430g2203", "msp430g2210",
2299 "msp430g2211", "msp430g2212", "msp430g2213",
2300 "msp430g2221", "msp430g2230", "msp430g2231",
2301 "msp430g2232", "msp430g2233", "msp430g2252",
2302 "msp430g2253", "msp430g2302", "msp430g2303",
2303 "msp430g2312", "msp430g2313", "msp430g2332",
2304 "msp430g2333", "msp430g2352", "msp430g2353",
2305 "msp430g2402", "msp430g2403", "msp430g2412",
2306 "msp430g2413", "msp430g2432", "msp430g2433",
2307 "msp430g2444", "msp430g2452", "msp430g2453",
2308 "msp430g2513", "msp430g2533", "msp430g2544",
2309 "msp430g2553", "msp430g2744", "msp430g2755",
2310 "msp430g2855", "msp430g2955", "msp430l092",
2311 "msp430p112", "msp430p313", "msp430p315",
2312 "msp430p315s", "msp430p325", "msp430tch5e"
2314 static const char * cached_match
= NULL
;
2315 static bool cached_result
;
2318 if (msp430_hwmult_type
== NONE
)
2321 if (target_mcu
== NULL
|| msp430_hwmult_type
!= AUTO
)
2324 if (target_mcu
== cached_match
)
2325 return cached_result
;
2327 cached_match
= target_mcu
;
2328 for (i
= ARRAY_SIZE (known_nomult_mcus
); i
--;)
2329 if (strcasecmp (target_mcu
, known_nomult_mcus
[i
]) == 0)
2330 return cached_result
= true;
2332 return cached_result
= false;
2335 /* This function does the same as the default, but it will replace GCC
2336 function names with the MSPABI-specified ones. */
2339 msp430_output_labelref (FILE *file
, const char *name
)
2343 for (i
= 0; helper_function_name_mappings
[i
].gcc_name
; i
++)
2344 if (strcmp (helper_function_name_mappings
[i
].gcc_name
, name
) == 0)
2346 name
= helper_function_name_mappings
[i
].ti_name
;
2350 /* If we have been given a specific MCU name then we may be
2351 able to make use of its hardware multiply capabilities. */
2352 if (msp430_hwmult_type
!= NONE
)
2354 if (strcmp ("__mspabi_mpyi", name
) == 0)
2356 if (msp430_use_f5_series_hwmult ())
2357 name
= "__mulhi2_f5";
2358 else if (! msp430_no_hwmult ())
2361 else if (strcmp ("__mspabi_mpyl", name
) == 0)
2363 if (msp430_use_f5_series_hwmult ())
2364 name
= "__mulsi2_f5";
2365 else if (use_32bit_hwmult ())
2366 name
= "__mulsi2_hw32";
2367 else if (! msp430_no_hwmult ())
2375 /* Common code for msp430_print_operand... */
2378 msp430_print_operand_raw (FILE * file
, rtx op
)
2382 switch (GET_CODE (op
))
2385 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
2391 fprintf (file
, "%#" HOST_WIDE_INT_PRINT
"x", i
);
2393 fprintf (file
, "%" HOST_WIDE_INT_PRINT
"d", i
);
2401 output_addr_const (file
, op
);
2405 print_rtl (file
, op
);
2410 #undef TARGET_PRINT_OPERAND_ADDRESS
2411 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
2413 /* Output to stdio stream FILE the assembler syntax for an
2414 instruction operand that is a memory reference whose address
2418 msp430_print_operand_addr (FILE * file
, rtx addr
)
2420 switch (GET_CODE (addr
))
2423 msp430_print_operand_raw (file
, XEXP (addr
, 1));
2424 gcc_assert (REG_P (XEXP (addr
, 0)));
2425 fprintf (file
, "(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
2429 fprintf (file
, "@");
2436 fprintf (file
, "&");
2443 msp430_print_operand_raw (file
, addr
);
2446 #undef TARGET_PRINT_OPERAND
2447 #define TARGET_PRINT_OPERAND msp430_print_operand
2449 /* A low 16-bits of int/lower of register pair
2450 B high 16-bits of int/higher of register pair
2451 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
2452 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
2453 H like %B (for backwards compatibility)
2455 J an integer without a # prefix
2456 L like %A (for backwards compatibility)
2457 O offset of the top of the stack
2458 Q like X but generates an A postfix
2459 R inverse of condition code, unsigned.
2460 X X instruction postfix in large mode
2463 b .B or .W or .A, depending upon the mode
2465 r inverse of condition code
2466 x like X but only for pointers. */
2469 msp430_print_operand (FILE * file
, rtx op
, int letter
)
2473 /* We can't use c, n, a, or l. */
2477 gcc_assert (CONST_INT_P (op
));
2478 /* Print the constant value, less one. */
2479 fprintf (file
, "#%ld", INTVAL (op
) - 1);
2482 gcc_assert (CONST_INT_P (op
));
2483 /* Print the constant value, less four. */
2484 fprintf (file
, "#%ld", INTVAL (op
) - 4);
2487 if (GET_CODE (op
) == CONST_INT
)
2489 /* Inverse of constants */
2490 int i
= INTVAL (op
);
2491 fprintf (file
, "%d", ~i
);
2496 case 'r': /* Conditional jump where the condition is reversed. */
2497 switch (GET_CODE (op
))
2499 case EQ
: fprintf (file
, "NE"); break;
2500 case NE
: fprintf (file
, "EQ"); break;
2501 case GEU
: fprintf (file
, "LO"); break;
2502 case LTU
: fprintf (file
, "HS"); break;
2503 case GE
: fprintf (file
, "L"); break;
2504 case LT
: fprintf (file
, "GE"); break;
2505 /* Assume these have reversed operands. */
2506 case GTU
: fprintf (file
, "HS"); break;
2507 case LEU
: fprintf (file
, "LO"); break;
2508 case GT
: fprintf (file
, "GE"); break;
2509 case LE
: fprintf (file
, "L"); break;
2511 msp430_print_operand_raw (file
, op
);
2515 case 'R': /* Conditional jump where the operands are reversed. */
2516 switch (GET_CODE (op
))
2518 case GTU
: fprintf (file
, "LO"); break;
2519 case LEU
: fprintf (file
, "HS"); break;
2520 case GT
: fprintf (file
, "L"); break;
2521 case LE
: fprintf (file
, "GE"); break;
2523 msp430_print_operand_raw (file
, op
);
2527 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
2528 gcc_assert (CONST_INT_P (op
));
2529 fprintf (file
, "#%d", 1 << INTVAL (op
));
2532 switch (GET_MODE (op
))
2534 case QImode
: fprintf (file
, ".B"); return;
2535 case HImode
: fprintf (file
, ".W"); return;
2536 case PSImode
: fprintf (file
, ".A"); return;
2537 case SImode
: fprintf (file
, ".A"); return;
2542 case 'L': /* Low half. */
2543 switch (GET_CODE (op
))
2546 op
= adjust_address (op
, Pmode
, 0);
2551 op
= GEN_INT (INTVAL (op
) & 0xffff);
2555 /* If you get here, figure out a test case :-) */
2560 case 'H': /* high half */
2561 switch (GET_CODE (op
))
2564 op
= adjust_address (op
, Pmode
, 2);
2567 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 1);
2570 op
= GEN_INT (INTVAL (op
) >> 16);
2574 /* If you get here, figure out a test case :-) */
2579 switch (GET_CODE (op
))
2582 op
= adjust_address (op
, Pmode
, 3);
2585 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 2);
2588 op
= GEN_INT ((long long) INTVAL (op
) >> 32);
2592 /* If you get here, figure out a test case :-) */
2597 switch (GET_CODE (op
))
2600 op
= adjust_address (op
, Pmode
, 4);
2603 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 3);
2606 op
= GEN_INT ((long long) INTVAL (op
) >> 48);
2610 /* If you get here, figure out a test case :-) */
2616 /* This is used to turn, for example, an ADD opcode into an ADDX
2617 opcode when we're using 20-bit addresses. */
2618 if (TARGET_LARGE
|| GET_MODE (op
) == PSImode
)
2619 fprintf (file
, "X");
2620 /* We don't care which operand we use, but we want 'X' in the MD
2621 file, so we do it this way. */
2625 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
2626 if (GET_MODE (op
) == PSImode
)
2627 fprintf (file
, "X");
2631 /* Likewise, for BR -> BRA. */
2633 fprintf (file
, "A");
2637 /* Computes the offset to the top of the stack for the current frame.
2638 This has to be done here rather than in, say, msp430_expand_builtin()
2639 because builtins are expanded before the frame layout is determined. */
2640 fprintf (file
, "%d",
2641 msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, STACK_POINTER_REGNUM
)
2642 - (TARGET_LARGE
? 4 : 2));
2646 gcc_assert (GET_CODE (op
) == CONST_INT
);
2650 output_operand_lossage ("invalid operand prefix");
2654 switch (GET_CODE (op
))
2657 msp430_print_operand_raw (file
, op
);
2661 addr
= XEXP (op
, 0);
2662 msp430_print_operand_addr (file
, addr
);
2666 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTRACT
)
2669 switch (INTVAL (XEXP (op
, 2)))
2672 fprintf (file
, "#lo (");
2673 msp430_print_operand_raw (file
, XEXP (op
, 0));
2674 fprintf (file
, ")");
2678 fprintf (file
, "#hi (");
2679 msp430_print_operand_raw (file
, XEXP (op
, 0));
2680 fprintf (file
, ")");
2684 output_operand_lossage ("invalid zero extract");
2694 fprintf (file
, "#");
2695 msp430_print_operand_raw (file
, op
);
2698 case EQ
: fprintf (file
, "EQ"); break;
2699 case NE
: fprintf (file
, "NE"); break;
2700 case GEU
: fprintf (file
, "HS"); break;
2701 case LTU
: fprintf (file
, "LO"); break;
2702 case GE
: fprintf (file
, "GE"); break;
2703 case LT
: fprintf (file
, "L"); break;
2706 print_rtl (file
, op
);
2715 msp430_return_addr_rtx (int count
)
2721 ra_size
= TARGET_LARGE
? 4 : 2;
2722 if (crtl
->args
.pretend_args_size
)
2725 return gen_rtx_MEM (Pmode
, gen_rtx_PLUS (Pmode
, arg_pointer_rtx
, GEN_INT (- ra_size
)));
2729 msp430_incoming_return_addr_rtx (void)
2731 return gen_rtx_MEM (Pmode
, stack_pointer_rtx
);
2734 /* Instruction generation stuff. */
2736 /* Generate a sequence of instructions to sign-extend an HI
2737 value into an SI value. Handles the tricky case where
2738 we are overwriting the destination. */
2741 msp430x_extendhisi (rtx
* operands
)
2743 if (REGNO (operands
[0]) == REGNO (operands
[1]))
2744 /* Low word of dest == source word. */
2745 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
2748 /* Note: This sequence is approximately the same length as invoking a helper
2749 function to perform the sign-extension, as in:
2753 CALL __mspabi_srai_15
2756 but this version does not involve any function calls or using argument
2757 registers, so it reduces register pressure. */
2758 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
2760 if (REGNO (operands
[0]) + 1 == REGNO (operands
[1]))
2761 /* High word of dest == source word. */
2762 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
2764 /* No overlap between dest and source. */
2765 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
2768 /* Likewise for logical right shifts. */
2770 msp430x_logical_shift_right (rtx amount
)
2772 /* The MSP430X's logical right shift instruction - RRUM - does
2773 not use an extension word, so we cannot encode a repeat count.
2774 Try various alternatives to work around this. If the count
2775 is in a register we are stuck, hence the assert. */
2776 gcc_assert (CONST_INT_P (amount
));
2778 if (INTVAL (amount
) <= 0
2779 || INTVAL (amount
) >= 16)
2780 return "# nop logical shift.";
2782 if (INTVAL (amount
) > 0
2783 && INTVAL (amount
) < 5)
2784 return "rrum.w\t%2, %0"; /* Two bytes. */
2786 if (INTVAL (amount
) > 4
2787 && INTVAL (amount
) < 9)
2788 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
2790 /* First we logically shift right by one. Now we know
2791 that the top bit is zero and we can use the arithmetic
2792 right shift instruction to perform the rest of the shift. */
2793 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
2796 struct gcc_target targetm
= TARGET_INITIALIZER
;
2798 #include "gt-msp430.h"