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"
29 #include "fold-const.h"
30 #include "stor-layout.h"
33 #include "insn-config.h"
34 #include "conditions.h"
36 #include "insn-attr.h"
45 #include "insn-codes.h"
49 #include "diagnostic-core.h"
56 #include "cfgcleanup.h"
60 #include "langhooks.h"
61 #include "msp430-protos.h"
66 /* This file should be included last. */
67 #include "target-def.h"
70 static void msp430_compute_frame_info (void);
74 /* Run-time Target Specification. */
78 struct GTY(()) machine_function
80 /* If set, the rest of the fields have been computed. */
82 /* Which registers need to be saved in the pro/epilogue. */
83 int need_to_save
[FIRST_PSEUDO_REGISTER
];
85 /* These fields describe the frame layout... */
87 /* 2/4 bytes for saved PC */
91 int framesize_outgoing
;
95 /* How much we adjust the stack when returning from an exception
100 /* This is our init_machine_status, as set in
101 msp_option_override. */
102 static struct machine_function
*
103 msp430_init_machine_status (void)
105 struct machine_function
*m
;
107 m
= ggc_cleared_alloc
<machine_function
> ();
112 #undef TARGET_OPTION_OVERRIDE
113 #define TARGET_OPTION_OVERRIDE msp430_option_override
115 static const char * msp430_mcu_names
[] =
117 "msp430afe221", "msp430afe222", "msp430afe223", "msp430afe231",
118 "msp430afe232", "msp430afe233", "msp430afe251", "msp430afe252",
119 "msp430afe253", "msp430c091", "msp430c092", "msp430c111",
120 "msp430c1111", "msp430c112", "msp430c1121", "msp430c1331",
121 "msp430c1351", "msp430c311s", "msp430c312", "msp430c313",
122 "msp430c314", "msp430c315", "msp430c323", "msp430c325",
123 "msp430c336", "msp430c337", "msp430c412", "msp430c413",
124 "msp430e112", "msp430e313", "msp430e315", "msp430e325",
125 "msp430e337", "msp430f110", "msp430f1101", "msp430f1101a",
126 "msp430f1111", "msp430f1111a", "msp430f112", "msp430f1121",
127 "msp430f1121a", "msp430f1122", "msp430f1132", "msp430f122",
128 "msp430f1222", "msp430f123", "msp430f1232", "msp430f133",
129 "msp430f135", "msp430f147", "msp430f1471", "msp430f148",
130 "msp430f1481", "msp430f149", "msp430f1491", "msp430f155",
131 "msp430f156", "msp430f157", "msp430f1610", "msp430f1611",
132 "msp430f1612", "msp430f167", "msp430f168", "msp430f169",
133 "msp430f2001", "msp430f2002", "msp430f2003", "msp430f2011",
134 "msp430f2012", "msp430f2013", "msp430f2101", "msp430f2111",
135 "msp430f2112", "msp430f2121", "msp430f2122", "msp430f2131",
136 "msp430f2132", "msp430f2232", "msp430f2234", "msp430f2252",
137 "msp430f2254", "msp430f2272", "msp430f2274", "msp430f233",
138 "msp430f2330", "msp430f235", "msp430f2350", "msp430f2370",
139 "msp430f2410", "msp430f247", "msp430f2471", "msp430f248",
140 "msp430f2481", "msp430f249", "msp430f2491", "msp430f412",
141 "msp430f413", "msp430f4132", "msp430f415", "msp430f4152",
142 "msp430f417", "msp430f423", "msp430f423a", "msp430f425",
143 "msp430f4250", "msp430f425a", "msp430f4260", "msp430f427",
144 "msp430f4270", "msp430f427a", "msp430f435", "msp430f4351",
145 "msp430f436", "msp430f4361", "msp430f437", "msp430f4371",
146 "msp430f438", "msp430f439", "msp430f447", "msp430f448",
147 "msp430f4481", "msp430f449", "msp430f4491", "msp430f477",
148 "msp430f478", "msp430f4783", "msp430f4784", "msp430f479",
149 "msp430f4793", "msp430f4794", "msp430fe423", "msp430fe4232",
150 "msp430fe423a", "msp430fe4242", "msp430fe425", "msp430fe4252",
151 "msp430fe425a", "msp430fe427", "msp430fe4272", "msp430fe427a",
152 "msp430fg4250", "msp430fg4260", "msp430fg4270", "msp430fg437",
153 "msp430fg438", "msp430fg439", "msp430fg477", "msp430fg478",
154 "msp430fg479", "msp430fw423", "msp430fw425", "msp430fw427",
155 "msp430fw428", "msp430fw429", "msp430g2001", "msp430g2101",
156 "msp430g2102", "msp430g2111", "msp430g2112", "msp430g2113",
157 "msp430g2121", "msp430g2131", "msp430g2132", "msp430g2152",
158 "msp430g2153", "msp430g2201", "msp430g2202", "msp430g2203",
159 "msp430g2210", "msp430g2211", "msp430g2212", "msp430g2213",
160 "msp430g2221", "msp430g2230", "msp430g2231", "msp430g2232",
161 "msp430g2233", "msp430g2252", "msp430g2253", "msp430g2302",
162 "msp430g2303", "msp430g2312", "msp430g2313", "msp430g2332",
163 "msp430g2333", "msp430g2352", "msp430g2353", "msp430g2402",
164 "msp430g2403", "msp430g2412", "msp430g2413", "msp430g2432",
165 "msp430g2433", "msp430g2444", "msp430g2452", "msp430g2453",
166 "msp430g2513", "msp430g2533", "msp430g2544", "msp430g2553",
167 "msp430g2744", "msp430g2755", "msp430g2855", "msp430g2955",
168 "msp430i2020", "msp430i2021", "msp430i2030", "msp430i2031",
169 "msp430i2040", "msp430i2041", "msp430l092", "msp430p112",
170 "msp430p313", "msp430p315", "msp430p315s", "msp430p325",
171 "msp430p337", "msp430tch5e"
174 /* Generate a C preprocessor symbol based upon the MCU selected by the user.
175 If a specific MCU has not been selected then return a generic symbol instead. */
178 msp430_mcu_name (void)
183 static char mcu_name
[64];
185 snprintf (mcu_name
, sizeof (mcu_name
) - 1, "__%s__", target_mcu
);
186 for (i
= strlen (mcu_name
); i
--;)
187 mcu_name
[i
] = TOUPPER (mcu_name
[i
]);
191 return msp430x
? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
195 msp430_option_override (void)
197 init_machine_status
= msp430_init_machine_status
;
201 if (strcasecmp (target_cpu
, "msp430x") == 0)
203 else /* target_cpu == "msp430" - already handled by the front end. */
206 /* Note - the front end has already ensured at most
207 one of target_cpu and target_mcu will be set. */
212 /* If we are given an MCU name, we assume that it supports 430X.
213 Then we check to see if it is one of the known MCUs that only
217 for (i
= ARRAY_SIZE (msp430_mcu_names
); i
--;)
218 if (strcasecmp (msp430_mcu_names
[i
], target_mcu
) == 0)
223 /* It is not an error if we do not match the MCU name. There are
227 if (TARGET_LARGE
&& !msp430x
)
228 error ("-mlarge requires a 430X-compatible -mmcu=");
230 if (msp430_code_region
== UPPER
&& ! msp430x
)
231 error ("-mcode-region=upper requires 430X-compatible cpu");
232 if (msp430_data_region
== UPPER
&& ! msp430x
)
233 error ("-mdata-region=upper requires 430X-compatible cpu");
235 if (flag_exceptions
|| flag_non_call_exceptions
236 || flag_unwind_tables
|| flag_asynchronous_unwind_tables
)
237 flag_omit_frame_pointer
= false;
239 flag_omit_frame_pointer
= true;
241 /* This is a hack to work around a problem with the newlib build
242 mechanism. Newlib always appends CFLAGS to the end of the GCC
243 command line and always sets -O2 in CFLAGS. Thus it is not
244 possible to build newlib with -Os enabled. Until now... */
245 if (TARGET_OPT_SPACE
&& optimize
< 3)
249 #undef TARGET_SCALAR_MODE_SUPPORTED_P
250 #define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
253 msp430_scalar_mode_supported_p (machine_mode m
)
255 if (m
== PSImode
&& msp430x
)
261 return default_scalar_mode_supported_p (m
);
268 #undef TARGET_MS_BITFIELD_LAYOUT_P
269 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
272 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED
)
281 /* Implements HARD_REGNO_NREGS. MSP430X registers can hold a single
282 PSImode value, but not an SImode value. */
284 msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED
,
287 if (mode
== PSImode
&& msp430x
)
289 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
293 /* Implements HARD_REGNO_NREGS_HAS_PADDING. */
295 msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED
,
298 if (mode
== PSImode
&& msp430x
)
300 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
304 /* Implements HARD_REGNO_NREGS_WITH_PADDING. */
306 msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED
,
311 return msp430_hard_regno_nregs (regno
, mode
);
314 /* Implements HARD_REGNO_MODE_OK. */
316 msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED
,
319 return regno
<= (ARG_POINTER_REGNUM
- msp430_hard_regno_nregs (regno
, mode
));
322 /* Implements MODES_TIEABLE_P. */
324 msp430_modes_tieable_p (machine_mode mode1
, machine_mode mode2
)
326 if ((mode1
== PSImode
|| mode2
== SImode
)
327 || (mode1
== SImode
|| mode2
== PSImode
))
330 return ((GET_MODE_CLASS (mode1
) == MODE_FLOAT
331 || GET_MODE_CLASS (mode1
) == MODE_COMPLEX_FLOAT
)
332 == (GET_MODE_CLASS (mode2
) == MODE_FLOAT
333 || GET_MODE_CLASS (mode2
) == MODE_COMPLEX_FLOAT
));
336 #undef TARGET_FRAME_POINTER_REQUIRED
337 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
340 msp430_frame_pointer_required (void)
345 #undef TARGET_CAN_ELIMINATE
346 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
349 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED
,
350 const int to_reg ATTRIBUTE_UNUSED
)
355 /* Implements INITIAL_ELIMINATION_OFFSET. */
357 msp430_initial_elimination_offset (int from
, int to
)
359 int rv
= 0; /* As if arg to arg. */
361 msp430_compute_frame_info ();
365 case STACK_POINTER_REGNUM
:
366 rv
+= cfun
->machine
->framesize_outgoing
;
367 rv
+= cfun
->machine
->framesize_locals
;
369 case FRAME_POINTER_REGNUM
:
370 rv
+= cfun
->machine
->framesize_regs
;
371 /* Allow for the saved return address. */
372 rv
+= (TARGET_LARGE
? 4 : 2);
373 /* NB/ No need to allow for crtl->args.pretend_args_size.
374 GCC does that for us. */
382 case FRAME_POINTER_REGNUM
:
383 /* Allow for the fall through above. */
384 rv
-= (TARGET_LARGE
? 4 : 2);
385 rv
-= cfun
->machine
->framesize_regs
;
386 case ARG_POINTER_REGNUM
:
395 /* Named Address Space support */
398 /* Return the appropriate mode for a named address pointer. */
399 #undef TARGET_ADDR_SPACE_POINTER_MODE
400 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
401 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
402 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
405 msp430_addr_space_pointer_mode (addr_space_t addrspace
)
410 case ADDR_SPACE_GENERIC
:
412 case ADDR_SPACE_NEAR
:
419 /* Function pointers are stored in unwind_word sized
420 variables, so make sure that unwind_word is big enough. */
421 #undef TARGET_UNWIND_WORD_MODE
422 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
425 msp430_unwind_word_mode (void)
427 return TARGET_LARGE
? PSImode
: HImode
;
430 /* Determine if one named address space is a subset of another. */
431 #undef TARGET_ADDR_SPACE_SUBSET_P
432 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
434 msp430_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
436 if (subset
== superset
)
439 return (subset
!= ADDR_SPACE_FAR
&& superset
== ADDR_SPACE_FAR
);
442 #undef TARGET_ADDR_SPACE_CONVERT
443 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
444 /* Convert from one address space to another. */
446 msp430_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
448 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
449 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
452 if (to_as
!= ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_FAR
)
454 /* This is unpredictable, as we're truncating off usable address
458 return gen_rtx_CONST (HImode
, op
);
460 result
= gen_reg_rtx (HImode
);
461 emit_insn (gen_truncpsihi2 (result
, op
));
464 else if (to_as
== ADDR_SPACE_FAR
&& from_as
!= ADDR_SPACE_FAR
)
466 /* This always works. */
469 return gen_rtx_CONST (PSImode
, op
);
471 result
= gen_reg_rtx (PSImode
);
472 emit_insn (gen_zero_extendhipsi2 (result
, op
));
479 /* Stack Layout and Calling Conventions. */
481 /* For each function, we list the gcc version and the TI version on
482 each line, where we're converting the function names. */
483 static char const * const special_convention_function_names
[] =
485 "__muldi3", "__mspabi_mpyll",
486 "__udivdi3", "__mspabi_divull",
487 "__umoddi3", "__mspabi_remull",
488 "__divdi3", "__mspabi_divlli",
489 "__moddi3", "__mspabi_remlli",
493 "__adddf3", "__mspabi_addd",
494 "__subdf3", "__mspabi_subd",
495 "__muldf3", "__mspabi_mpyd",
496 "__divdf3", "__mspabi_divd",
501 /* TRUE if the function passed is a "speical" function. Special
502 functions pass two DImode parameters in registers. */
504 msp430_special_register_convention_p (const char *name
)
508 for (i
= 0; special_convention_function_names
[i
]; i
++)
509 if (! strcmp (name
, special_convention_function_names
[i
]))
515 #undef TARGET_FUNCTION_VALUE_REGNO_P
516 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
519 msp430_function_value_regno_p (unsigned int regno
)
525 #undef TARGET_FUNCTION_VALUE
526 #define TARGET_FUNCTION_VALUE msp430_function_value
529 msp430_function_value (const_tree ret_type
,
530 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
531 bool outgoing ATTRIBUTE_UNUSED
)
533 return gen_rtx_REG (TYPE_MODE (ret_type
), 12);
536 #undef TARGET_LIBCALL_VALUE
537 #define TARGET_LIBCALL_VALUE msp430_libcall_value
540 msp430_libcall_value (machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
542 return gen_rtx_REG (mode
, 12);
545 /* Implements INIT_CUMULATIVE_ARGS. */
547 msp430_init_cumulative_args (CUMULATIVE_ARGS
*ca
,
548 tree fntype ATTRIBUTE_UNUSED
,
549 rtx libname ATTRIBUTE_UNUSED
,
550 tree fndecl ATTRIBUTE_UNUSED
,
551 int n_named_args ATTRIBUTE_UNUSED
)
554 memset (ca
, 0, sizeof(*ca
));
559 fname
= IDENTIFIER_POINTER (DECL_NAME (fndecl
));
561 fname
= XSTR (libname
, 0);
565 if (fname
&& msp430_special_register_convention_p (fname
))
569 /* Helper function for argument passing; this function is the common
570 code that determines where an argument will be passed. */
572 msp430_evaluate_arg (cumulative_args_t cap
,
574 const_tree type ATTRIBUTE_UNUSED
,
577 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
578 int nregs
= GET_MODE_SIZE (mode
);
590 nregs
= (nregs
+ 1) / 2;
594 /* Function is passed two DImode operands, in R8:R11 and
604 for (i
= 0; i
< 4; i
++)
605 if (! ca
->reg_used
[i
])
608 ca
->start_reg
= CA_FIRST_REG
+ i
;
613 for (i
= 0; i
< 3; i
++)
614 if (! ca
->reg_used
[i
] && ! ca
->reg_used
[i
+ 1])
617 ca
->start_reg
= CA_FIRST_REG
+ i
;
620 if (! ca
->reg_used
[3] && ca
->can_split
)
624 ca
->start_reg
= CA_FIRST_REG
+ 3;
631 if (! ca
->reg_used
[0]
632 && ! ca
->reg_used
[1]
633 && ! ca
->reg_used
[2]
634 && ! ca
->reg_used
[3])
637 ca
->start_reg
= CA_FIRST_REG
;
644 #undef TARGET_PROMOTE_PROTOTYPES
645 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
648 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED
)
653 #undef TARGET_FUNCTION_ARG
654 #define TARGET_FUNCTION_ARG msp430_function_arg
657 msp430_function_arg (cumulative_args_t cap
,
662 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
664 msp430_evaluate_arg (cap
, mode
, type
, named
);
667 return gen_rtx_REG (mode
, ca
->start_reg
);
672 #undef TARGET_ARG_PARTIAL_BYTES
673 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
676 msp430_arg_partial_bytes (cumulative_args_t cap
,
681 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
683 msp430_evaluate_arg (cap
, mode
, type
, named
);
685 if (ca
->reg_count
&& ca
->mem_count
)
686 return ca
->reg_count
* UNITS_PER_WORD
;
691 #undef TARGET_PASS_BY_REFERENCE
692 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
695 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED
,
698 bool named ATTRIBUTE_UNUSED
)
700 return (mode
== BLKmode
701 || (type
&& TREE_CODE (type
) == RECORD_TYPE
)
702 || (type
&& TREE_CODE (type
) == UNION_TYPE
));
705 #undef TARGET_CALLEE_COPIES
706 #define TARGET_CALLEE_COPIES msp430_callee_copies
709 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED
,
710 machine_mode mode ATTRIBUTE_UNUSED
,
711 const_tree type ATTRIBUTE_UNUSED
,
712 bool named ATTRIBUTE_UNUSED
)
717 #undef TARGET_FUNCTION_ARG_ADVANCE
718 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
721 msp430_function_arg_advance (cumulative_args_t cap
,
726 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
729 msp430_evaluate_arg (cap
, mode
, type
, named
);
731 if (ca
->start_reg
>= CA_FIRST_REG
)
732 for (i
= 0; i
< ca
->reg_count
; i
++)
733 ca
->reg_used
[i
+ ca
->start_reg
- CA_FIRST_REG
] = 1;
738 #undef TARGET_FUNCTION_ARG_BOUNDARY
739 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
742 msp430_function_arg_boundary (machine_mode mode
, const_tree type
)
745 && int_size_in_bytes (type
) > 1)
747 if (GET_MODE_BITSIZE (mode
) > 8)
752 #undef TARGET_RETURN_IN_MEMORY
753 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
756 msp430_return_in_memory (const_tree ret_type
, const_tree fntype ATTRIBUTE_UNUSED
)
758 machine_mode mode
= TYPE_MODE (ret_type
);
761 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == RECORD_TYPE
)
762 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == UNION_TYPE
))
765 if (GET_MODE_SIZE (mode
) > 8)
771 #undef TARGET_GET_RAW_ARG_MODE
772 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
775 msp430_get_raw_arg_mode (int regno
)
777 return (regno
== ARG_POINTER_REGNUM
) ? VOIDmode
: Pmode
;
780 #undef TARGET_GET_RAW_RESULT_MODE
781 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
784 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED
)
789 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
790 #define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
792 #include "gimplify.h"
793 #include "gimple-expr.h"
796 msp430_gimplify_va_arg_expr (tree valist
, tree type
, gimple_seq
*pre_p
,
799 tree addr
, t
, type_size
, rounded_size
, valist_tmp
;
800 unsigned HOST_WIDE_INT align
, boundary
;
803 indirect
= pass_by_reference (NULL
, TYPE_MODE (type
), type
, false);
805 type
= build_pointer_type (type
);
807 align
= PARM_BOUNDARY
/ BITS_PER_UNIT
;
808 boundary
= targetm
.calls
.function_arg_boundary (TYPE_MODE (type
), type
);
810 /* When we align parameter on stack for caller, if the parameter
811 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
812 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
814 if (boundary
> MAX_SUPPORTED_STACK_ALIGNMENT
)
815 boundary
= MAX_SUPPORTED_STACK_ALIGNMENT
;
817 boundary
/= BITS_PER_UNIT
;
819 /* Hoist the valist value into a temporary for the moment. */
820 valist_tmp
= get_initialized_tmp_var (valist
, pre_p
, NULL
);
822 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
823 requires greater alignment, we must perform dynamic alignment. */
825 && !integer_zerop (TYPE_SIZE (type
)))
827 /* FIXME: This is where this function diverts from targhooks.c:
828 std_gimplify_va_arg_expr(). It works, but I do not know why... */
829 if (! POINTER_TYPE_P (type
))
831 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
832 fold_build_pointer_plus_hwi (valist_tmp
, boundary
- 1));
833 gimplify_and_add (t
, pre_p
);
835 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
836 fold_build2 (BIT_AND_EXPR
, TREE_TYPE (valist
),
838 build_int_cst (TREE_TYPE (valist
), -boundary
)));
839 gimplify_and_add (t
, pre_p
);
845 /* If the actual alignment is less than the alignment of the type,
846 adjust the type accordingly so that we don't assume strict alignment
847 when dereferencing the pointer. */
848 boundary
*= BITS_PER_UNIT
;
849 if (boundary
< TYPE_ALIGN (type
))
851 type
= build_variant_type_copy (type
);
852 TYPE_ALIGN (type
) = boundary
;
855 /* Compute the rounded size of the type. */
856 type_size
= size_in_bytes (type
);
857 rounded_size
= round_up (type_size
, align
);
859 /* Reduce rounded_size so it's sharable with the postqueue. */
860 gimplify_expr (&rounded_size
, pre_p
, post_p
, is_gimple_val
, fb_rvalue
);
865 /* Compute new value for AP. */
866 t
= fold_build_pointer_plus (valist_tmp
, rounded_size
);
867 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist
, t
);
868 gimplify_and_add (t
, pre_p
);
870 addr
= fold_convert (build_pointer_type (type
), addr
);
873 addr
= build_va_arg_indirect_ref (addr
);
875 addr
= build_va_arg_indirect_ref (addr
);
880 /* Addressing Modes */
882 #undef TARGET_LEGITIMATE_ADDRESS_P
883 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
886 reg_ok_for_addr (rtx r
, bool strict
)
890 if (strict
&& rn
>= FIRST_PSEUDO_REGISTER
)
891 rn
= reg_renumber
[rn
];
892 if (strict
&& 0 <= rn
&& rn
< FIRST_PSEUDO_REGISTER
)
900 msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED
,
901 rtx x ATTRIBUTE_UNUSED
,
902 bool strict ATTRIBUTE_UNUSED
)
904 switch (GET_CODE (x
))
910 if (REG_P (XEXP (x
, 0)))
912 if (GET_MODE (x
) != GET_MODE (XEXP (x
, 0)))
914 if (!reg_ok_for_addr (XEXP (x
, 0), strict
))
916 switch (GET_CODE (XEXP (x
, 1)))
929 if (!reg_ok_for_addr (x
, strict
))
942 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
943 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
946 msp430_addr_space_legitimate_address_p (machine_mode mode
,
949 addr_space_t as ATTRIBUTE_UNUSED
)
951 return msp430_legitimate_address_p (mode
, x
, strict
);
954 #undef TARGET_ASM_INTEGER
955 #define TARGET_ASM_INTEGER msp430_asm_integer
957 msp430_asm_integer (rtx x
, unsigned int size
, int aligned_p
)
959 int c
= GET_CODE (x
);
961 if (size
== 3 && GET_MODE (x
) == PSImode
)
967 if (c
== SYMBOL_REF
|| c
== CONST
|| c
== LABEL_REF
|| c
== CONST_INT
968 || c
== PLUS
|| c
== MINUS
)
970 fprintf (asm_out_file
, "\t.long\t");
971 output_addr_const (asm_out_file
, x
);
972 fputc ('\n', asm_out_file
);
977 return default_assemble_integer (x
, size
, aligned_p
);
980 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
981 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra
983 msp430_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED
, rtx x
)
989 #undef TARGET_LEGITIMATE_CONSTANT_P
990 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
993 msp430_legitimate_constant (machine_mode mode
, rtx x
)
995 return ! CONST_INT_P (x
)
997 /* GCC does not know the width of the PSImode, so make
998 sure that it does not try to use a constant value that
1000 || (INTVAL (x
) < (1 << 20) && INTVAL (x
) >= (-1 << 20));
1004 #undef TARGET_RTX_COSTS
1005 #define TARGET_RTX_COSTS msp430_rtx_costs
1007 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED
,
1009 int outer_code ATTRIBUTE_UNUSED
,
1010 int opno ATTRIBUTE_UNUSED
,
1012 bool speed ATTRIBUTE_UNUSED
)
1017 if (GET_MODE (x
) == SImode
&& outer_code
== SET
)
1019 *total
= COSTS_N_INSNS (4);
1028 *total
= COSTS_N_INSNS (100);
1036 /* Function Entry and Exit */
1038 /* The MSP430 call frame looks like this:
1041 +--------------------+
1045 +--------------------+ <-- "arg pointer"
1047 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
1049 +--------------------+
1050 | SR if this func has|
1051 | been called via an |
1053 +--------------------+ <-- SP before prologue, also AP
1055 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
1057 +--------------------+ <-- "frame pointer"
1061 +--------------------+
1065 +--------------------+ <-- SP during function
1070 /* We use this to wrap all emitted insns in the prologue, so they get
1071 the "frame-related" (/f) flag set. */
1075 RTX_FRAME_RELATED_P (x
) = 1;
1079 /* This is the one spot that decides if a register is to be saved and
1080 restored in the prologue/epilogue. */
1082 msp430_preserve_reg_p (int regno
)
1084 /* PC, SP, SR, and the constant generator. */
1088 /* FIXME: add interrupt, EH, etc. */
1089 if (crtl
->calls_eh_return
)
1092 /* Shouldn't be more than the above, but just in case... */
1093 if (fixed_regs
[regno
])
1096 /* Interrupt handlers save all registers they use, even
1097 ones which are call saved. If they call other functions
1098 then *every* register is saved. */
1099 if (msp430_is_interrupt_func ())
1100 return ! crtl
->is_leaf
|| df_regs_ever_live_p (regno
);
1102 if (!call_used_regs
[regno
]
1103 && df_regs_ever_live_p (regno
))
1109 /* Compute all the frame-related fields in our machine_function
1112 msp430_compute_frame_info (void)
1116 cfun
->machine
->computed
= 1;
1117 cfun
->machine
->framesize_regs
= 0;
1118 cfun
->machine
->framesize_locals
= get_frame_size ();
1119 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
1121 for (i
= 0; i
< ARG_POINTER_REGNUM
; i
++)
1122 if (msp430_preserve_reg_p (i
))
1124 cfun
->machine
->need_to_save
[i
] = 1;
1125 cfun
->machine
->framesize_regs
+= (TARGET_LARGE
? 4 : 2);
1128 cfun
->machine
->need_to_save
[i
] = 0;
1130 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
1131 cfun
->machine
->framesize_locals
++;
1133 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
1134 + cfun
->machine
->framesize_locals
1135 + cfun
->machine
->framesize_outgoing
);
1138 /* Attribute Handling. */
1140 const char * const ATTR_INTR
= "interrupt";
1141 const char * const ATTR_WAKEUP
= "wakeup";
1142 const char * const ATTR_NAKED
= "naked";
1143 const char * const ATTR_REENT
= "reentrant";
1144 const char * const ATTR_CRIT
= "critical";
1145 const char * const ATTR_LOWER
= "lower";
1146 const char * const ATTR_UPPER
= "upper";
1147 const char * const ATTR_EITHER
= "either";
1150 has_attr (const char * attr
, tree decl
)
1152 if (decl
== NULL_TREE
)
1154 return lookup_attribute (attr
, DECL_ATTRIBUTES (decl
)) != NULL_TREE
;
1158 is_interrupt_func (tree decl
= current_function_decl
)
1160 return has_attr (ATTR_INTR
, decl
);
1163 /* Returns true if the current function has the "interrupt" attribute. */
1166 msp430_is_interrupt_func (void)
1168 return is_interrupt_func (current_function_decl
);
1172 is_wakeup_func (tree decl
= current_function_decl
)
1174 return is_interrupt_func (decl
) && has_attr (ATTR_WAKEUP
, decl
);
1178 is_naked_func (tree decl
= current_function_decl
)
1180 return has_attr (ATTR_NAKED
, decl
);
1184 is_reentrant_func (tree decl
= current_function_decl
)
1186 return has_attr (ATTR_REENT
, decl
);
1190 is_critical_func (tree decl
= current_function_decl
)
1192 return has_attr (ATTR_CRIT
, decl
);
1195 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
1196 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS msp430_allocate_stack_slots_for_args
1199 msp430_allocate_stack_slots_for_args (void)
1201 /* Naked functions should not allocate stack slots for arguments. */
1202 return ! is_naked_func ();
1205 /* Verify MSP430 specific attributes. */
1206 #define TREE_NAME_EQ(NAME, STR) (strcmp (IDENTIFIER_POINTER (NAME), (STR)) == 0)
1209 msp430_attr (tree
* node
,
1212 int flags ATTRIBUTE_UNUSED
,
1213 bool * no_add_attrs
)
1215 gcc_assert (DECL_P (* node
));
1219 gcc_assert (TREE_NAME_EQ (name
, ATTR_INTR
));
1221 tree value
= TREE_VALUE (args
);
1223 switch (TREE_CODE (value
))
1226 if ( strcmp (TREE_STRING_POINTER (value
), "reset")
1227 && strcmp (TREE_STRING_POINTER (value
), "nmi")
1228 && strcmp (TREE_STRING_POINTER (value
), "watchdog"))
1229 /* Allow the attribute to be added - the linker script
1230 being used may still recognise this name. */
1231 warning (OPT_Wattributes
,
1232 "unrecognised interrupt vector argument of %qE attribute",
1237 if (wi::gtu_p (value
, 63))
1238 /* Allow the attribute to be added - the linker script
1239 being used may still recognise this value. */
1240 warning (OPT_Wattributes
,
1241 "numeric argument of %qE attribute must be in range 0..63",
1246 warning (OPT_Wattributes
,
1247 "argument of %qE attribute is not a string constant or number",
1249 *no_add_attrs
= true;
1254 const char * message
= NULL
;
1256 if (TREE_CODE (* node
) != FUNCTION_DECL
)
1258 message
= "%qE attribute only applies to functions";
1260 else if (TREE_NAME_EQ (name
, ATTR_INTR
))
1262 if (TREE_CODE (TREE_TYPE (* node
)) == FUNCTION_TYPE
1263 && ! VOID_TYPE_P (TREE_TYPE (TREE_TYPE (* node
))))
1264 message
= "interrupt handlers must be void";
1266 else if (TREE_NAME_EQ (name
, ATTR_REENT
))
1268 if (is_naked_func (* node
))
1269 message
= "naked functions cannot be reentrant";
1270 else if (is_critical_func (* node
))
1271 message
= "critical functions cannot be reentrant";
1273 else if (TREE_NAME_EQ (name
, ATTR_CRIT
))
1275 if (is_naked_func (* node
))
1276 message
= "naked functions cannot be critical";
1277 else if (is_reentrant_func (* node
))
1278 message
= "reentranct functions cannot be critical";
1280 else if (TREE_NAME_EQ (name
, ATTR_NAKED
))
1282 if (is_critical_func (* node
))
1283 message
= "critical functions cannot be naked";
1284 else if (is_reentrant_func (* node
))
1285 message
= "reentrant functions cannot be naked";
1290 warning (OPT_Wattributes
, message
, name
);
1291 * no_add_attrs
= true;
1298 msp430_section_attr (tree
* node
,
1301 int flags ATTRIBUTE_UNUSED
,
1302 bool * no_add_attrs ATTRIBUTE_UNUSED
)
1304 gcc_assert (DECL_P (* node
));
1305 gcc_assert (args
== NULL
);
1307 const char * message
= NULL
;
1309 if (TREE_NAME_EQ (name
, ATTR_UPPER
))
1311 if (has_attr (ATTR_LOWER
, * node
))
1312 message
= "already marked with 'lower' attribute";
1313 else if (has_attr (ATTR_EITHER
, * node
))
1314 message
= "already marked with 'either' attribute";
1316 message
= "upper attribute needs a 430X cpu";
1318 else if (TREE_NAME_EQ (name
, ATTR_LOWER
))
1320 if (has_attr (ATTR_UPPER
, * node
))
1321 message
= "already marked with 'upper' attribute";
1322 else if (has_attr (ATTR_EITHER
, * node
))
1323 message
= "already marked with 'either' attribute";
1327 gcc_assert (TREE_NAME_EQ (name
, ATTR_EITHER
));
1329 if (has_attr (ATTR_LOWER
, * node
))
1330 message
= "already marked with 'lower' attribute";
1331 else if (has_attr (ATTR_UPPER
, * node
))
1332 message
= "already marked with 'upper' attribute";
1337 warning (OPT_Wattributes
, message
, name
);
1338 * no_add_attrs
= true;
1344 #undef TARGET_ATTRIBUTE_TABLE
1345 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
1347 /* Table of MSP430-specific attributes. */
1348 const struct attribute_spec msp430_attribute_table
[] =
1350 /* Name min_num_args type_req, affects_type_identity
1351 max_num_args, fn_type_req
1352 decl_req handler. */
1353 { ATTR_INTR
, 0, 1, true, false, false, msp430_attr
, false },
1354 { ATTR_NAKED
, 0, 0, true, false, false, msp430_attr
, false },
1355 { ATTR_REENT
, 0, 0, true, false, false, msp430_attr
, false },
1356 { ATTR_CRIT
, 0, 0, true, false, false, msp430_attr
, false },
1357 { ATTR_WAKEUP
, 0, 0, true, false, false, msp430_attr
, false },
1359 { ATTR_LOWER
, 0, 0, true, false, false, msp430_section_attr
, false },
1360 { ATTR_UPPER
, 0, 0, true, false, false, msp430_section_attr
, false },
1361 { ATTR_EITHER
, 0, 0, true, false, false, msp430_section_attr
, false },
1363 { NULL
, 0, 0, false, false, false, NULL
, false }
1366 #undef TARGET_ASM_FUNCTION_PROLOGUE
1367 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
1370 msp430_start_function (FILE *outfile
, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED
)
1374 fprintf (outfile
, "; start of function\n");
1376 if (DECL_ATTRIBUTES (current_function_decl
) != NULL_TREE
)
1378 fprintf (outfile
, "; attributes: ");
1379 if (is_naked_func ())
1380 fprintf (outfile
, "naked ");
1381 if (msp430_is_interrupt_func ())
1382 fprintf (outfile
, "interrupt ");
1383 if (is_reentrant_func ())
1384 fprintf (outfile
, "reentrant ");
1385 if (is_critical_func ())
1386 fprintf (outfile
, "critical ");
1387 if (is_wakeup_func ())
1388 fprintf (outfile
, "wakeup ");
1389 fprintf (outfile
, "\n");
1392 fprintf (outfile
, "; framesize_regs: %d\n", cfun
->machine
->framesize_regs
);
1393 fprintf (outfile
, "; framesize_locals: %d\n", cfun
->machine
->framesize_locals
);
1394 fprintf (outfile
, "; framesize_outgoing: %d\n", cfun
->machine
->framesize_outgoing
);
1395 fprintf (outfile
, "; framesize: %d\n", cfun
->machine
->framesize
);
1396 fprintf (outfile
, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, FRAME_POINTER_REGNUM
));
1397 fprintf (outfile
, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM
, STACK_POINTER_REGNUM
));
1400 fprintf (outfile
, "; saved regs:");
1401 for (r
= 0; r
< ARG_POINTER_REGNUM
; r
++)
1402 if (cfun
->machine
->need_to_save
[r
])
1404 fprintf (outfile
, " %s", reg_names
[r
]);
1408 fprintf (outfile
, "(none)");
1409 fprintf (outfile
, "\n");
1412 /* Common code to change the stack pointer. */
1414 increment_stack (HOST_WIDE_INT amount
)
1417 rtx sp
= stack_pointer_rtx
;
1424 inc
= GEN_INT (- amount
);
1426 F (emit_insn (gen_subpsi3 (sp
, sp
, inc
)));
1428 F (emit_insn (gen_subhi3 (sp
, sp
, inc
)));
1432 inc
= GEN_INT (amount
);
1434 emit_insn (gen_addpsi3 (sp
, sp
, inc
));
1436 emit_insn (gen_addhi3 (sp
, sp
, inc
));
1441 msp430_start_function (FILE *file
, const char *name
, tree decl
)
1445 int_attr
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl
));
1446 if (int_attr
!= NULL_TREE
)
1448 tree intr_vector
= TREE_VALUE (int_attr
);
1450 if (intr_vector
!= NULL_TREE
)
1454 intr_vector
= TREE_VALUE (intr_vector
);
1456 /* The interrupt attribute has a vector value. Turn this into a
1457 section name, switch to that section and put the address of
1458 the current function into that vector slot. Note msp430_attr()
1459 has already verified the vector name for us. */
1460 if (TREE_CODE (intr_vector
) == STRING_CST
)
1461 sprintf (buf
, "__interrupt_vector_%.80s",
1462 TREE_STRING_POINTER (intr_vector
));
1463 else /* TREE_CODE (intr_vector) == INTEGER_CST */
1464 sprintf (buf
, "__interrupt_vector_%u",
1465 (unsigned int) TREE_INT_CST_LOW (intr_vector
));
1467 switch_to_section (get_section (buf
, SECTION_CODE
, decl
));
1468 fputs ("\t.word\t", file
);
1469 assemble_name (file
, name
);
1475 switch_to_section (function_section (decl
));
1476 ASM_OUTPUT_FUNCTION_LABEL (file
, name
, decl
);
1479 static const char * const lower_prefix
= ".lower";
1480 static const char * const upper_prefix
= ".upper";
1481 static const char * const either_prefix
= ".either";
1483 /* Generate a prefix for a section name, based upon
1484 the region into which the object should be placed. */
1487 gen_prefix (tree decl
)
1489 if (DECL_ONE_ONLY (decl
))
1492 /* If the user has specified a particular section then do not use any prefix. */
1493 if (has_attr ("section", decl
))
1496 /* If the object has __attribute__((lower)) then use the ".lower." prefix. */
1497 if (has_attr (ATTR_LOWER
, decl
))
1498 return lower_prefix
;
1500 /* If we are compiling for the MSP430 then we do not support the upper region. */
1504 if (has_attr (ATTR_UPPER
, decl
))
1505 return upper_prefix
;
1507 if (has_attr (ATTR_EITHER
, decl
))
1508 return either_prefix
;
1510 if (TREE_CODE (decl
) == FUNCTION_DECL
)
1512 if (msp430_code_region
== LOWER
)
1513 return lower_prefix
;
1515 if (msp430_code_region
== UPPER
)
1516 return upper_prefix
;
1518 if (msp430_code_region
== EITHER
)
1519 return either_prefix
;
1523 if (msp430_data_region
== LOWER
)
1524 return lower_prefix
;
1526 if (msp430_data_region
== UPPER
)
1527 return upper_prefix
;
1529 if (msp430_data_region
== EITHER
)
1530 return either_prefix
;
1536 #undef TARGET_ASM_SELECT_SECTION
1537 #define TARGET_ASM_SELECT_SECTION msp430_select_section
1540 msp430_select_section (tree decl
, int reloc
, unsigned HOST_WIDE_INT align
)
1542 gcc_assert (decl
!= NULL_TREE
);
1544 if (TREE_CODE (decl
) == STRING_CST
1545 || TREE_CODE (decl
) == CONSTRUCTOR
1546 || TREE_CODE (decl
) == INTEGER_CST
1547 || TREE_CODE (decl
) == VECTOR_CST
1548 || TREE_CODE (decl
) == COMPLEX_CST
)
1549 return default_select_section (decl
, reloc
, align
);
1551 /* In large mode we must make sure that interrupt handlers are put into
1552 low memory as the vector table only accepts 16-bit addresses. */
1553 if (TARGET_LARGE
&& TREE_CODE (decl
) == FUNCTION_DECL
&& is_interrupt_func (decl
))
1554 return get_section (".lowtext", SECTION_CODE
| SECTION_WRITE
, decl
);
1556 const char * prefix
= gen_prefix (decl
);
1559 if (TREE_CODE (decl
) == FUNCTION_DECL
)
1560 return text_section
;
1562 return default_select_section (decl
, reloc
, align
);
1566 switch (categorize_decl_for_section (decl
, reloc
))
1568 case SECCAT_TEXT
: sec
= ".text"; break;
1569 case SECCAT_DATA
: sec
= ".data"; break;
1570 case SECCAT_BSS
: sec
= ".bss"; break;
1571 case SECCAT_RODATA
: sec
= ".rodata"; break;
1573 case SECCAT_RODATA_MERGE_STR
:
1574 case SECCAT_RODATA_MERGE_STR_INIT
:
1575 case SECCAT_RODATA_MERGE_CONST
:
1576 case SECCAT_SRODATA
:
1577 case SECCAT_DATA_REL
:
1578 case SECCAT_DATA_REL_LOCAL
:
1579 case SECCAT_DATA_REL_RO
:
1580 case SECCAT_DATA_REL_RO_LOCAL
:
1585 return default_select_section (decl
, reloc
, align
);
1591 const char * dec_name
= DECL_SECTION_NAME (decl
);
1592 char * name
= ACONCAT ((prefix
, sec
, dec_name
, NULL
));
1594 return get_named_section (decl
, name
, 0);
1597 #undef TARGET_ASM_FUNCTION_SECTION
1598 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
1601 msp430_function_section (tree decl
, enum node_frequency freq
, bool startup
, bool exit
)
1605 gcc_assert (DECL_SECTION_NAME (decl
) != NULL
);
1606 name
= DECL_SECTION_NAME (decl
);
1608 const char * prefix
= gen_prefix (decl
);
1610 || strncmp (name
, prefix
, strlen (prefix
)) == 0)
1611 return default_function_section (decl
, freq
, startup
, exit
);
1613 name
= ACONCAT ((prefix
, name
, NULL
));
1614 return get_named_section (decl
, name
, 0);
1617 #undef TARGET_SECTION_TYPE_FLAGS
1618 #define TARGET_SECTION_TYPE_FLAGS msp430_section_type_flags
1621 msp430_section_type_flags (tree decl
, const char * name
, int reloc
)
1623 if (strncmp (name
, lower_prefix
, strlen (lower_prefix
)) == 0)
1624 name
+= strlen (lower_prefix
);
1625 else if (strncmp (name
, upper_prefix
, strlen (upper_prefix
)) == 0)
1626 name
+= strlen (upper_prefix
);
1627 else if (strncmp (name
, either_prefix
, strlen (either_prefix
)) == 0)
1628 name
+= strlen (either_prefix
);
1630 return default_section_type_flags (decl
, name
, reloc
);
1633 #undef TARGET_ASM_UNIQUE_SECTION
1634 #define TARGET_ASM_UNIQUE_SECTION msp430_unique_section
1637 msp430_unique_section (tree decl
, int reloc
)
1639 gcc_assert (decl
!= NULL_TREE
);
1641 /* In large mode we must make sure that interrupt handlers are put into
1642 low memory as the vector table only accepts 16-bit addresses. */
1643 if (TARGET_LARGE
&& TREE_CODE (decl
) == FUNCTION_DECL
&& is_interrupt_func (decl
))
1645 set_decl_section_name (decl
, ".lowtext");
1649 default_unique_section (decl
, reloc
);
1651 const char * prefix
;
1653 if ( TREE_CODE (decl
) == STRING_CST
1654 || TREE_CODE (decl
) == CONSTRUCTOR
1655 || TREE_CODE (decl
) == INTEGER_CST
1656 || TREE_CODE (decl
) == VECTOR_CST
1657 || TREE_CODE (decl
) == COMPLEX_CST
1658 || (prefix
= gen_prefix (decl
)) == NULL
1662 const char * dec_name
= DECL_SECTION_NAME (decl
);
1663 char * name
= ACONCAT ((prefix
, dec_name
, NULL
));
1665 set_decl_section_name (decl
, name
);
1668 /* Emit a declaration of a common symbol.
1669 If a data region is in use then put the symbol into the
1670 equivalent .bss section instead. */
1673 msp430_output_aligned_decl_common (FILE * stream
,
1676 unsigned HOST_WIDE_INT size
,
1679 if (msp430_data_region
== ANY
)
1681 fprintf (stream
, COMMON_ASM_OP
);
1682 assemble_name (stream
, name
);
1683 fprintf (stream
, "," HOST_WIDE_INT_PRINT_UNSIGNED
",%u\n",
1684 size
, align
/ BITS_PER_UNIT
);
1691 sec
= msp430_select_section (decl
, 0, align
);
1693 switch (msp430_data_region
)
1695 case UPPER
: sec
= get_named_section (NULL
, ".upper.bss", 0); break;
1696 case LOWER
: sec
= get_named_section (NULL
, ".lower.bss", 0); break;
1697 case EITHER
: sec
= get_named_section (NULL
, ".either.bss", 0); break;
1701 gcc_assert (sec
!= NULL
);
1703 switch_to_section (sec
);
1704 ASM_OUTPUT_ALIGN (stream
, floor_log2 (align
/ BITS_PER_UNIT
));
1705 targetm
.asm_out
.globalize_label (stream
, name
);
1706 ASM_WEAKEN_LABEL (stream
, name
);
1707 ASM_OUTPUT_LABEL (stream
, name
);
1708 ASM_OUTPUT_SKIP (stream
, size
? size
: 1);
1713 msp430_do_not_relax_short_jumps (void)
1715 /* When placing code into "either" low or high memory we do not want the linker
1716 to grow the size of sections, which it can do if it is encounters a branch to
1717 a label that is too far away. So we tell the cbranch patterns to avoid using
1718 short jumps when there is a chance that the instructions will end up in a low
1721 msp430_code_region
== EITHER
1722 || msp430_code_region
== LOWER
1723 || has_attr (ATTR_EITHER
, current_function_decl
)
1724 || has_attr (ATTR_LOWER
, current_function_decl
);
1729 MSP430_BUILTIN_BIC_SR
,
1730 MSP430_BUILTIN_BIS_SR
,
1731 MSP430_BUILTIN_DELAY_CYCLES
,
1735 static GTY(()) tree msp430_builtins
[(int) MSP430_BUILTIN_max
];
1738 msp430_init_builtins (void)
1740 tree void_ftype_int
= build_function_type_list (void_type_node
, integer_type_node
, NULL
);
1741 tree void_ftype_longlong
= build_function_type_list (void_type_node
, long_long_integer_type_node
, NULL
);
1743 msp430_builtins
[MSP430_BUILTIN_BIC_SR
] =
1744 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int
,
1745 MSP430_BUILTIN_BIC_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
1747 msp430_builtins
[MSP430_BUILTIN_BIS_SR
] =
1748 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int
,
1749 MSP430_BUILTIN_BIS_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
1751 msp430_builtins
[MSP430_BUILTIN_DELAY_CYCLES
] =
1752 add_builtin_function ( "__delay_cycles", void_ftype_longlong
,
1753 MSP430_BUILTIN_DELAY_CYCLES
, BUILT_IN_MD
, NULL
, NULL_TREE
);
1757 msp430_builtin_decl (unsigned code
, bool initialize ATTRIBUTE_UNUSED
)
1761 case MSP430_BUILTIN_BIC_SR
:
1762 case MSP430_BUILTIN_BIS_SR
:
1763 case MSP430_BUILTIN_DELAY_CYCLES
:
1764 return msp430_builtins
[code
];
1766 return error_mark_node
;
1770 /* These constants are really register reads, which are faster than
1771 regular constants. */
1773 cg_magic_constant (HOST_WIDE_INT c
)
1791 msp430_expand_delay_cycles (rtx arg
)
1793 HOST_WIDE_INT i
, c
, n
;
1794 /* extra cycles for MSP430X instructions */
1795 #define CYCX(M,X) (msp430x ? (X) : (M))
1797 if (GET_CODE (arg
) != CONST_INT
)
1799 error ("__delay_cycles() only takes constant arguments");
1805 if (HOST_BITS_PER_WIDE_INT
> 32)
1809 error ("__delay_cycles only takes non-negative cycle counts.");
1814 emit_insn (gen_delay_cycles_start (arg
));
1816 /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
1817 if (c
> 3 * 0xffff + CYCX (7, 10))
1820 /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
1821 if (c
>= 0x10000 * 7 + CYCX (14, 16))
1824 c
-= CYCX (14, 16) + 7 * 0x10000;
1827 if ((unsigned long long) i
> 0xffffffffULL
)
1829 error ("__delay_cycles is limited to 32-bit loop counts.");
1835 i
= (c
- CYCX (14, 16)) / 7;
1836 c
-= CYCX (14, 16) + i
* 7;
1839 if (cg_magic_constant (i
& 0xffff))
1841 if (cg_magic_constant ((i
>> 16) & 0xffff))
1845 emit_insn (gen_delay_cycles_32x (GEN_INT (i
), GEN_INT (n
- c
)));
1847 emit_insn (gen_delay_cycles_32 (GEN_INT (i
), GEN_INT (n
- c
)));
1850 /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
1854 i
= (c
- CYCX (7, 10)) / 3;
1855 c
-= CYCX (7, 10) + i
* 3;
1857 if (cg_magic_constant (i
))
1861 emit_insn (gen_delay_cycles_16x (GEN_INT (i
), GEN_INT (n
- c
)));
1863 emit_insn (gen_delay_cycles_16 (GEN_INT (i
), GEN_INT (n
- c
)));
1868 emit_insn (gen_delay_cycles_2 ());
1874 emit_insn (gen_delay_cycles_1 ());
1878 emit_insn (gen_delay_cycles_end (arg
));
1884 msp430_expand_builtin (tree exp
,
1885 rtx target ATTRIBUTE_UNUSED
,
1886 rtx subtarget ATTRIBUTE_UNUSED
,
1887 machine_mode mode ATTRIBUTE_UNUSED
,
1888 int ignore ATTRIBUTE_UNUSED
)
1890 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
1891 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
1892 rtx arg1
= expand_normal (CALL_EXPR_ARG (exp
, 0));
1894 if (fcode
== MSP430_BUILTIN_DELAY_CYCLES
)
1895 return msp430_expand_delay_cycles (arg1
);
1897 if (! msp430_is_interrupt_func ())
1899 error ("MSP430 builtin functions only work inside interrupt handlers");
1903 if (! REG_P (arg1
) && ! CONSTANT_P (arg1
))
1904 arg1
= force_reg (mode
, arg1
);
1908 case MSP430_BUILTIN_BIC_SR
: emit_insn (gen_bic_SR (arg1
)); break;
1909 case MSP430_BUILTIN_BIS_SR
: emit_insn (gen_bis_SR (arg1
)); break;
1911 internal_error ("bad builtin code");
1917 #undef TARGET_INIT_BUILTINS
1918 #define TARGET_INIT_BUILTINS msp430_init_builtins
1920 #undef TARGET_EXPAND_BUILTIN
1921 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
1923 #undef TARGET_BUILTIN_DECL
1924 #define TARGET_BUILTIN_DECL msp430_builtin_decl
1927 msp430_expand_prologue (void)
1931 /* Always use stack_pointer_rtx instead of calling
1932 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
1933 that there is a single rtx representing the stack pointer,
1934 namely stack_pointer_rtx, and uses == to recognize it. */
1935 rtx sp
= stack_pointer_rtx
;
1938 if (is_naked_func ())
1940 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
1941 examines the output of the gen_prologue() function. */
1942 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
1946 emit_insn (gen_prologue_start_marker ());
1948 if (is_critical_func ())
1950 emit_insn (gen_push_intr_state ());
1951 emit_insn (gen_disable_interrupts ());
1953 else if (is_reentrant_func ())
1954 emit_insn (gen_disable_interrupts ());
1956 if (!cfun
->machine
->computed
)
1957 msp430_compute_frame_info ();
1959 if (flag_stack_usage_info
)
1960 current_function_static_stack_size
= cfun
->machine
->framesize
;
1962 if (crtl
->args
.pretend_args_size
)
1966 gcc_assert (crtl
->args
.pretend_args_size
== 2);
1968 p
= emit_insn (gen_grow_and_swap ());
1970 /* Document the stack decrement... */
1971 note
= F (gen_rtx_SET (stack_pointer_rtx
,
1972 gen_rtx_MINUS (Pmode
, stack_pointer_rtx
, GEN_INT (2))));
1973 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
1975 /* ...and the establishment of a new location for the return address. */
1976 note
= F (gen_rtx_SET (gen_rtx_MEM (Pmode
,
1977 gen_rtx_PLUS (Pmode
,
1981 add_reg_note (p
, REG_CFA_OFFSET
, note
);
1985 for (i
= 15; i
>= 4; i
--)
1986 if (cfun
->machine
->need_to_save
[i
])
1991 for (seq
= i
- 1; seq
>= 4 && cfun
->machine
->need_to_save
[seq
]; seq
--)
1997 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
1998 p
= F (emit_insn (gen_pushm (gen_rtx_REG (Pmode
, i
),
2001 note
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (count
+ 1));
2003 XVECEXP (note
, 0, 0)
2004 = F (gen_rtx_SET (stack_pointer_rtx
,
2005 gen_rtx_PLUS (Pmode
,
2007 GEN_INT (count
* (TARGET_LARGE
? -4 : -2)))));
2009 /* *sp-- = R[i-j] */
2013 for (j
= 0; j
< count
; j
++)
2016 int ofs
= (count
- j
- 1) * (TARGET_LARGE
? 4 : 2);
2019 addr
= gen_rtx_PLUS (Pmode
, sp
, GEN_INT (ofs
));
2021 addr
= stack_pointer_rtx
;
2023 XVECEXP (note
, 0, j
+ 1) =
2024 F (gen_rtx_SET (gen_rtx_MEM (Pmode
, addr
),
2025 gen_rtx_REG (Pmode
, i
- j
)) );
2028 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
2032 F (emit_insn (gen_push (gen_rtx_REG (Pmode
, i
))));
2035 if (frame_pointer_needed
)
2036 F (emit_move_insn (gen_rtx_REG (Pmode
, FRAME_POINTER_REGNUM
), sp
));
2038 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
2040 increment_stack (- fs
);
2042 emit_insn (gen_prologue_end_marker ());
2046 msp430_expand_epilogue (int is_eh
)
2052 if (is_naked_func ())
2054 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2055 examines the output of the gen_epilogue() function. */
2056 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
2060 if (cfun
->machine
->need_to_save
[10])
2062 /* Check for a helper function. */
2063 helper_n
= 7; /* For when the loop below never sees a match. */
2064 for (i
= 9; i
>= 4; i
--)
2065 if (!cfun
->machine
->need_to_save
[i
])
2069 if (cfun
->machine
->need_to_save
[i
])
2078 emit_insn (gen_epilogue_start_marker ());
2080 if (cfun
->decl
&& strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun
->decl
)), "main") == 0)
2081 emit_insn (gen_msp430_refsym_need_exit ());
2083 if (is_wakeup_func ())
2084 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
2085 status register current residing on the stack. When this function
2086 executes its RETI instruction the SR will be updated with this saved
2087 value, thus ensuring that the processor is woken up from any low power
2088 state in which it may be residing. */
2089 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
2091 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
2093 increment_stack (fs
);
2097 /* We need to add the right "SP" register save just after the
2098 regular ones, so that when we pop it off we're in the EH
2099 return frame, not this one. This overwrites our own return
2100 address, but we're not going to be returning anyway. */
2101 rtx r12
= gen_rtx_REG (Pmode
, 12);
2102 rtx (*addPmode
)(rtx
, rtx
, rtx
) = TARGET_LARGE
? gen_addpsi3
: gen_addhi3
;
2104 /* R12 will hold the new SP. */
2105 i
= cfun
->machine
->framesize_regs
;
2106 emit_move_insn (r12
, stack_pointer_rtx
);
2107 emit_insn (addPmode (r12
, r12
, EH_RETURN_STACKADJ_RTX
));
2108 emit_insn (addPmode (r12
, r12
, GEN_INT (i
)));
2109 emit_move_insn (gen_rtx_MEM (Pmode
, plus_constant (Pmode
, stack_pointer_rtx
, i
)), r12
);
2112 for (i
= 4; i
<= 15; i
++)
2113 if (cfun
->machine
->need_to_save
[i
])
2117 for (seq
= i
+ 1; seq
<= 15 && cfun
->machine
->need_to_save
[seq
]; seq
++)
2123 /* Note: With TARGET_LARGE we still use
2124 POPM as POPX.A is two bytes bigger. */
2125 emit_insn (gen_popm (stack_pointer_rtx
, GEN_INT (seq
- 1),
2129 else if (i
== 11 - helper_n
2130 && ! msp430_is_interrupt_func ()
2131 && ! is_reentrant_func ()
2132 && ! is_critical_func ()
2133 && crtl
->args
.pretend_args_size
== 0
2134 /* Calling the helper takes as many bytes as the POP;RET sequence. */
2138 emit_insn (gen_epilogue_helper (GEN_INT (helper_n
)));
2142 emit_insn (gen_pop (gen_rtx_REG (Pmode
, i
)));
2147 /* Also pop SP, which puts us into the EH return frame. Except
2148 that you can't "pop" sp, you have to just load it off the
2150 emit_move_insn (stack_pointer_rtx
, gen_rtx_MEM (Pmode
, stack_pointer_rtx
));
2153 if (crtl
->args
.pretend_args_size
)
2154 emit_insn (gen_swap_and_shrink ());
2156 if (is_critical_func ())
2157 emit_insn (gen_pop_intr_state ());
2158 else if (is_reentrant_func ())
2159 emit_insn (gen_enable_interrupts ());
2161 emit_jump_insn (gen_msp_return ());
2164 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
2165 m32c_emit_eh_epilogue. */
2167 msp430_eh_return_stackadj_rtx (void)
2169 if (!cfun
->machine
->eh_stack_adjust
)
2173 sa
= gen_rtx_REG (Pmode
, 15);
2174 cfun
->machine
->eh_stack_adjust
= sa
;
2176 return cfun
->machine
->eh_stack_adjust
;
2179 /* This function is called before reload, to "fix" the stack in
2180 preparation for an EH return. */
2182 msp430_expand_eh_return (rtx eh_handler
)
2184 /* These are all Pmode */
2185 rtx ap
, sa
, ra
, tmp
;
2187 ap
= arg_pointer_rtx
;
2188 sa
= msp430_eh_return_stackadj_rtx ();
2192 tmp
= gen_rtx_PLUS (Pmode
, ap
, sa
);
2193 tmp
= plus_constant (Pmode
, tmp
, TARGET_LARGE
? -4 : -2);
2194 tmp
= gen_rtx_MEM (Pmode
, tmp
);
2195 emit_move_insn (tmp
, ra
);
2198 #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
2199 #define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
2201 msp430_init_dwarf_reg_sizes_extra (tree address
)
2204 rtx addr
= expand_normal (address
);
2205 rtx mem
= gen_rtx_MEM (BLKmode
, addr
);
2210 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
2212 unsigned int dnum
= DWARF_FRAME_REGNUM (i
);
2213 unsigned int rnum
= DWARF2_FRAME_REG_OUT (dnum
, 1);
2215 if (rnum
< DWARF_FRAME_REGISTERS
)
2217 HOST_WIDE_INT offset
= rnum
* GET_MODE_SIZE (QImode
);
2219 emit_move_insn (adjust_address (mem
, QImode
, offset
),
2220 gen_int_mode (4, QImode
));
2225 /* This is a list of MD patterns that implement fixed-count shifts. */
2231 rtx (*genfunc
)(rtx
,rtx
);
2233 const_shift_helpers
[] =
2235 #define CSH(N,C,X,G) { "__mspabi_" N, C, X, gen_##G }
2237 CSH ("slli", 1, 1, slli_1
),
2238 CSH ("slll", 1, 1, slll_1
),
2239 CSH ("slll", 2, 1, slll_2
),
2241 CSH ("srai", 1, 0, srai_1
),
2242 CSH ("sral", 1, 0, sral_1
),
2243 CSH ("sral", 2, 0, sral_2
),
2245 CSH ("srll", 1, 0, srll_1
),
2246 CSH ("srll", 2, 1, srll_2x
),
2251 /* The MSP430 ABI defines a number of helper functions that should be
2252 used for, for example, 32-bit shifts. This function is called to
2253 emit such a function, using the table above to optimize some
2256 msp430_expand_helper (rtx
*operands
, const char *helper_name
, bool const_variants
)
2259 char *helper_const
= NULL
;
2262 machine_mode arg0mode
= GET_MODE (operands
[0]);
2263 machine_mode arg1mode
= GET_MODE (operands
[1]);
2264 machine_mode arg2mode
= GET_MODE (operands
[2]);
2265 int have_430x
= msp430x
? 1 : 0;
2267 if (CONST_INT_P (operands
[2]))
2271 for (i
=0; const_shift_helpers
[i
].name
; i
++)
2273 if (const_shift_helpers
[i
].need_430x
<= have_430x
2274 && strcmp (helper_name
, const_shift_helpers
[i
].name
) == 0
2275 && INTVAL (operands
[2]) == const_shift_helpers
[i
].count
)
2277 emit_insn (const_shift_helpers
[i
].genfunc (operands
[0], operands
[1]));
2283 if (arg1mode
== VOIDmode
)
2284 arg1mode
= arg0mode
;
2285 if (arg2mode
== VOIDmode
)
2286 arg2mode
= arg0mode
;
2288 if (arg1mode
== SImode
)
2295 && CONST_INT_P (operands
[2])
2296 && INTVAL (operands
[2]) >= 1
2297 && INTVAL (operands
[2]) <= 15)
2299 /* Note that the INTVAL is limited in value and length by the conditional above. */
2300 int len
= strlen (helper_name
) + 4;
2301 helper_const
= (char *) xmalloc (len
);
2302 snprintf (helper_const
, len
, "%s_%d", helper_name
, (int) INTVAL (operands
[2]));
2305 emit_move_insn (gen_rtx_REG (arg1mode
, 12),
2308 emit_move_insn (gen_rtx_REG (arg2mode
, arg2
),
2311 c
= gen_call_value_internal (gen_rtx_REG (arg0mode
, 12),
2312 gen_rtx_SYMBOL_REF (VOIDmode
, helper_const
? helper_const
: helper_name
),
2314 c
= emit_call_insn (c
);
2315 RTL_CONST_CALL_P (c
) = 1;
2318 use_regs (&f
, 12, arg1sz
);
2320 use_regs (&f
, arg2
, 1);
2321 add_function_usage_to (c
, f
);
2323 emit_move_insn (operands
[0],
2324 gen_rtx_REG (arg0mode
, 12));
2327 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
2329 msp430_fixup_compare_operands (machine_mode my_mode
, rtx
* operands
)
2331 /* constants we're looking for, not constants which are allowed. */
2332 int const_op_idx
= 1;
2334 if (msp430_reversible_cmp_operator (operands
[0], VOIDmode
))
2337 if (GET_CODE (operands
[const_op_idx
]) != REG
2338 && GET_CODE (operands
[const_op_idx
]) != MEM
)
2339 operands
[const_op_idx
] = copy_to_mode_reg (my_mode
, operands
[const_op_idx
]);
2342 /* Simplify_gen_subreg() doesn't handle memory references the way we
2343 need it to below, so we use this function for when we must get a
2344 valid subreg in a "natural" state. */
2346 msp430_subreg (machine_mode mode
, rtx r
, machine_mode omode
, int byte
)
2350 if (GET_CODE (r
) == SUBREG
2351 && SUBREG_BYTE (r
) == 0)
2353 rtx ireg
= SUBREG_REG (r
);
2354 machine_mode imode
= GET_MODE (ireg
);
2356 /* special case for (HI (SI (PSI ...), 0)) */
2357 if (imode
== PSImode
2360 rv
= gen_rtx_SUBREG (mode
, ireg
, byte
);
2362 rv
= simplify_gen_subreg (mode
, ireg
, imode
, byte
);
2364 else if (GET_CODE (r
) == MEM
)
2365 rv
= adjust_address (r
, mode
, byte
);
2366 else if (GET_CODE (r
) == SYMBOL_REF
2367 && (byte
== 0 || byte
== 2)
2370 rv
= gen_rtx_ZERO_EXTRACT (HImode
, r
, GEN_INT (16), GEN_INT (8*byte
));
2371 rv
= gen_rtx_CONST (HImode
, r
);
2374 rv
= simplify_gen_subreg (mode
, r
, omode
, byte
);
2382 /* Called by movsi_x to generate the HImode operands. */
2384 msp430_split_movsi (rtx
*operands
)
2386 rtx op00
, op02
, op10
, op12
;
2388 op00
= msp430_subreg (HImode
, operands
[0], SImode
, 0);
2389 op02
= msp430_subreg (HImode
, operands
[0], SImode
, 2);
2391 if (GET_CODE (operands
[1]) == CONST
2392 || GET_CODE (operands
[1]) == SYMBOL_REF
)
2394 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
2395 op10
= gen_rtx_CONST (HImode
, op10
);
2396 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
2397 op12
= gen_rtx_CONST (HImode
, op12
);
2401 op10
= msp430_subreg (HImode
, operands
[1], SImode
, 0);
2402 op12
= msp430_subreg (HImode
, operands
[1], SImode
, 2);
2405 if (rtx_equal_p (operands
[0], operands
[1]))
2412 else if (rtx_equal_p (op00
, op12
)
2413 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
2414 || (REG_P (op00
) && reg_mentioned_p (op00
, op10
))
2415 /* Or storing (rN) into mem (rN). */
2416 || (REG_P (op10
) && reg_mentioned_p (op10
, op00
))
2434 /* The MSPABI specifies the names of various helper functions, many of
2435 which are compatible with GCC's helpers. This table maps the GCC
2436 name to the MSPABI name. */
2439 char const * const gcc_name
;
2440 char const * const ti_name
;
2442 helper_function_name_mappings
[] =
2444 /* Floating point to/from integer conversions. */
2445 { "__truncdfsf2", "__mspabi_cvtdf" },
2446 { "__extendsfdf2", "__mspabi_cvtfd" },
2447 { "__fixdfhi", "__mspabi_fixdi" },
2448 { "__fixdfsi", "__mspabi_fixdli" },
2449 { "__fixdfdi", "__mspabi_fixdlli" },
2450 { "__fixunsdfhi", "__mspabi_fixdu" },
2451 { "__fixunsdfsi", "__mspabi_fixdul" },
2452 { "__fixunsdfdi", "__mspabi_fixdull" },
2453 { "__fixsfhi", "__mspabi_fixfi" },
2454 { "__fixsfsi", "__mspabi_fixfli" },
2455 { "__fixsfdi", "__mspabi_fixflli" },
2456 { "__fixunsfhi", "__mspabi_fixfu" },
2457 { "__fixunsfsi", "__mspabi_fixful" },
2458 { "__fixunsfdi", "__mspabi_fixfull" },
2459 { "__floathisf", "__mspabi_fltif" },
2460 { "__floatsisf", "__mspabi_fltlif" },
2461 { "__floatdisf", "__mspabi_fltllif" },
2462 { "__floathidf", "__mspabi_fltid" },
2463 { "__floatsidf", "__mspabi_fltlid" },
2464 { "__floatdidf", "__mspabi_fltllid" },
2465 { "__floatunhisf", "__mspabi_fltuf" },
2466 { "__floatunsisf", "__mspabi_fltulf" },
2467 { "__floatundisf", "__mspabi_fltullf" },
2468 { "__floatunhidf", "__mspabi_fltud" },
2469 { "__floatunsidf", "__mspabi_fltuld" },
2470 { "__floatundidf", "__mspabi_fltulld" },
2472 /* Floating point comparisons. */
2473 /* GCC uses individual functions for each comparison, TI uses one
2474 compare <=> function. */
2476 /* Floating point arithmatic */
2477 { "__adddf3", "__mspabi_addd" },
2478 { "__addsf3", "__mspabi_addf" },
2479 { "__divdf3", "__mspabi_divd" },
2480 { "__divsf3", "__mspabi_divf" },
2481 { "__muldf3", "__mspabi_mpyd" },
2482 { "__mulsf3", "__mspabi_mpyf" },
2483 { "__subdf3", "__mspabi_subd" },
2484 { "__subsf3", "__mspabi_subf" },
2485 /* GCC does not use helper functions for negation */
2487 /* Integer multiply, divide, remainder. */
2488 { "__mulhi3", "__mspabi_mpyi" },
2489 { "__mulsi3", "__mspabi_mpyl" },
2490 { "__muldi3", "__mspabi_mpyll" },
2492 /* Clarify signed vs unsigned first. */
2493 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
2494 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
2497 { "__divhi3", "__mspabi_divi" },
2498 { "__divsi3", "__mspabi_divli" },
2499 { "__divdi3", "__mspabi_divlli" },
2500 { "__udivhi3", "__mspabi_divu" },
2501 { "__udivsi3", "__mspabi_divlu" },
2502 { "__udivdi3", "__mspabi_divllu" },
2503 { "__modhi3", "__mspabi_remi" },
2504 { "__modsi3", "__mspabi_remli" },
2505 { "__moddi3", "__mspabi_remlli" },
2506 { "__umodhi3", "__mspabi_remu" },
2507 { "__umodsi3", "__mspabi_remul" },
2508 { "__umoddi3", "__mspabi_remull" },
2510 /* Bitwise operations. */
2511 /* Rotation - no rotation support yet. */
2512 /* Logical left shift - gcc already does these itself. */
2513 /* Arithmetic left shift - gcc already does these itself. */
2514 /* Arithmetic right shift - gcc already does these itself. */
2519 /* Returns true if the current MCU supports an F5xxx series
2520 hardware multiper. */
2523 msp430_use_f5_series_hwmult (void)
2525 static const char * cached_match
= NULL
;
2526 static bool cached_result
;
2528 if (msp430_hwmult_type
== F5SERIES
)
2531 if (target_mcu
== NULL
|| msp430_hwmult_type
!= AUTO
)
2534 if (target_mcu
== cached_match
)
2535 return cached_result
;
2537 cached_match
= target_mcu
;
2539 if (strncasecmp (target_mcu
, "msp430f5", 8) == 0)
2540 return cached_result
= true;
2541 if (strncasecmp (target_mcu
, "msp430fr5", 9) == 0)
2542 return cached_result
= true;
2543 if (strncasecmp (target_mcu
, "msp430f6", 8) == 0)
2544 return cached_result
= true;
2546 static const char * known_f5_mult_mcus
[] =
2548 "cc430f5123", "cc430f5125", "cc430f5133",
2549 "cc430f5135", "cc430f5137", "cc430f5143",
2550 "cc430f5145", "cc430f5147", "cc430f6125",
2551 "cc430f6126", "cc430f6127", "cc430f6135",
2552 "cc430f6137", "cc430f6143", "cc430f6145",
2553 "cc430f6147", "msp430bt5190", "msp430sl5438a",
2558 for (i
= ARRAY_SIZE (known_f5_mult_mcus
); i
--;)
2559 if (strcasecmp (target_mcu
, known_f5_mult_mcus
[i
]) == 0)
2560 return cached_result
= true;
2562 return cached_result
= false;
2565 /* Returns true if the current MCU has a second generation
2566 32-bit hardware multiplier. */
2569 use_32bit_hwmult (void)
2571 static const char * known_32bit_mult_mcus
[] =
2573 "msp430f4783", "msp430f4793", "msp430f4784",
2574 "msp430f4794", "msp430f47126", "msp430f47127",
2575 "msp430f47163", "msp430f47173", "msp430f47183",
2576 "msp430f47193", "msp430f47166", "msp430f47176",
2577 "msp430f47186", "msp430f47196", "msp430f47167",
2578 "msp430f47177", "msp430f47187", "msp430f47197"
2580 static const char * cached_match
= NULL
;
2581 static bool cached_result
;
2584 if (msp430_hwmult_type
== LARGE
)
2587 if (target_mcu
== NULL
|| msp430_hwmult_type
!= AUTO
)
2590 if (target_mcu
== cached_match
)
2591 return cached_result
;
2593 cached_match
= target_mcu
;
2594 for (i
= ARRAY_SIZE (known_32bit_mult_mcus
); i
--;)
2595 if (strcasecmp (target_mcu
, known_32bit_mult_mcus
[i
]) == 0)
2596 return cached_result
= true;
2598 return cached_result
= false;
2601 /* Returns true if the current MCU does not have a
2602 hardware multiplier of any kind. */
2605 msp430_no_hwmult (void)
2607 static const char * known_nomult_mcus
[] =
2609 "msp430c091", "msp430c092", "msp430c111",
2610 "msp430c1111", "msp430c112", "msp430c1121",
2611 "msp430c1331", "msp430c1351", "msp430c311s",
2612 "msp430c312", "msp430c313", "msp430c314",
2613 "msp430c315", "msp430c323", "msp430c325",
2614 "msp430c412", "msp430c413", "msp430e112",
2615 "msp430e313", "msp430e315", "msp430e325",
2616 "msp430f110", "msp430f1101", "msp430f1101a",
2617 "msp430f1111", "msp430f1111a", "msp430f112",
2618 "msp430f1121", "msp430f1121a", "msp430f1122",
2619 "msp430f1132", "msp430f122", "msp430f1222",
2620 "msp430f123", "msp430f1232", "msp430f133",
2621 "msp430f135", "msp430f155", "msp430f156",
2622 "msp430f157", "msp430f2001", "msp430f2002",
2623 "msp430f2003", "msp430f2011", "msp430f2012",
2624 "msp430f2013", "msp430f2101", "msp430f2111",
2625 "msp430f2112", "msp430f2121", "msp430f2122",
2626 "msp430f2131", "msp430f2132", "msp430f2232",
2627 "msp430f2234", "msp430f2252", "msp430f2254",
2628 "msp430f2272", "msp430f2274", "msp430f412",
2629 "msp430f413", "msp430f4132", "msp430f415",
2630 "msp430f4152", "msp430f417", "msp430f4250",
2631 "msp430f4260", "msp430f4270", "msp430f435",
2632 "msp430f4351", "msp430f436", "msp430f4361",
2633 "msp430f437", "msp430f4371", "msp430f438",
2634 "msp430f439", "msp430f477", "msp430f478",
2635 "msp430f479", "msp430fe423", "msp430fe4232",
2636 "msp430fe423a", "msp430fe4242", "msp430fe425",
2637 "msp430fe4252", "msp430fe425a", "msp430fe427",
2638 "msp430fe4272", "msp430fe427a", "msp430fg4250",
2639 "msp430fg4260", "msp430fg4270", "msp430fg437",
2640 "msp430fg438", "msp430fg439", "msp430fg477",
2641 "msp430fg478", "msp430fg479", "msp430fr2032",
2642 "msp430fr2033", "msp430fr4131", "msp430fr4132",
2643 "msp430fr4133", "msp430fw423", "msp430fw425",
2644 "msp430fw427", "msp430fw428", "msp430fw429",
2645 "msp430g2001", "msp430g2101", "msp430g2102",
2646 "msp430g2111", "msp430g2112", "msp430g2113",
2647 "msp430g2121", "msp430g2131", "msp430g2132",
2648 "msp430g2152", "msp430g2153", "msp430g2201",
2649 "msp430g2202", "msp430g2203", "msp430g2210",
2650 "msp430g2211", "msp430g2212", "msp430g2213",
2651 "msp430g2221", "msp430g2230", "msp430g2231",
2652 "msp430g2232", "msp430g2233", "msp430g2252",
2653 "msp430g2253", "msp430g2302", "msp430g2303",
2654 "msp430g2312", "msp430g2313", "msp430g2332",
2655 "msp430g2333", "msp430g2352", "msp430g2353",
2656 "msp430g2402", "msp430g2403", "msp430g2412",
2657 "msp430g2413", "msp430g2432", "msp430g2433",
2658 "msp430g2444", "msp430g2452", "msp430g2453",
2659 "msp430g2513", "msp430g2533", "msp430g2544",
2660 "msp430g2553", "msp430g2744", "msp430g2755",
2661 "msp430g2855", "msp430g2955", "msp430l092",
2662 "msp430p112", "msp430p313", "msp430p315",
2663 "msp430p315s", "msp430p325", "msp430tch5e"
2665 static const char * cached_match
= NULL
;
2666 static bool cached_result
;
2669 if (msp430_hwmult_type
== NONE
)
2672 if (target_mcu
== NULL
|| msp430_hwmult_type
!= AUTO
)
2675 if (target_mcu
== cached_match
)
2676 return cached_result
;
2678 cached_match
= target_mcu
;
2679 for (i
= ARRAY_SIZE (known_nomult_mcus
); i
--;)
2680 if (strcasecmp (target_mcu
, known_nomult_mcus
[i
]) == 0)
2681 return cached_result
= true;
2683 return cached_result
= false;
2686 /* This function does the same as the default, but it will replace GCC
2687 function names with the MSPABI-specified ones. */
2690 msp430_output_labelref (FILE *file
, const char *name
)
2694 for (i
= 0; helper_function_name_mappings
[i
].gcc_name
; i
++)
2695 if (strcmp (helper_function_name_mappings
[i
].gcc_name
, name
) == 0)
2697 name
= helper_function_name_mappings
[i
].ti_name
;
2701 /* If we have been given a specific MCU name then we may be
2702 able to make use of its hardware multiply capabilities. */
2703 if (msp430_hwmult_type
!= NONE
)
2705 if (strcmp ("__mspabi_mpyi", name
) == 0)
2707 if (msp430_use_f5_series_hwmult ())
2708 name
= "__mulhi2_f5";
2709 else if (! msp430_no_hwmult ())
2712 else if (strcmp ("__mspabi_mpyl", name
) == 0)
2714 if (msp430_use_f5_series_hwmult ())
2715 name
= "__mulsi2_f5";
2716 else if (use_32bit_hwmult ())
2717 name
= "__mulsi2_hw32";
2718 else if (! msp430_no_hwmult ())
2726 /* Common code for msp430_print_operand... */
2729 msp430_print_operand_raw (FILE * file
, rtx op
)
2733 switch (GET_CODE (op
))
2736 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
2742 fprintf (file
, "%#" HOST_WIDE_INT_PRINT
"x", i
);
2744 fprintf (file
, "%" HOST_WIDE_INT_PRINT
"d", i
);
2752 output_addr_const (file
, op
);
2756 print_rtl (file
, op
);
2761 #undef TARGET_PRINT_OPERAND_ADDRESS
2762 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
2764 /* Output to stdio stream FILE the assembler syntax for an
2765 instruction operand that is a memory reference whose address
2769 msp430_print_operand_addr (FILE * file
, rtx addr
)
2771 switch (GET_CODE (addr
))
2774 msp430_print_operand_raw (file
, XEXP (addr
, 1));
2775 gcc_assert (REG_P (XEXP (addr
, 0)));
2776 fprintf (file
, "(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
2780 fprintf (file
, "@");
2787 fprintf (file
, "&");
2794 msp430_print_operand_raw (file
, addr
);
2797 #undef TARGET_PRINT_OPERAND
2798 #define TARGET_PRINT_OPERAND msp430_print_operand
2800 /* A low 16-bits of int/lower of register pair
2801 B high 16-bits of int/higher of register pair
2802 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
2803 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
2804 H like %B (for backwards compatibility)
2806 J an integer without a # prefix
2807 L like %A (for backwards compatibility)
2808 O offset of the top of the stack
2809 Q like X but generates an A postfix
2810 R inverse of condition code, unsigned.
2811 X X instruction postfix in large mode
2814 b .B or .W or .A, depending upon the mode
2816 r inverse of condition code
2817 x like X but only for pointers. */
2820 msp430_print_operand (FILE * file
, rtx op
, int letter
)
2824 /* We can't use c, n, a, or l. */
2828 gcc_assert (CONST_INT_P (op
));
2829 /* Print the constant value, less one. */
2830 fprintf (file
, "#%ld", INTVAL (op
) - 1);
2833 gcc_assert (CONST_INT_P (op
));
2834 /* Print the constant value, less four. */
2835 fprintf (file
, "#%ld", INTVAL (op
) - 4);
2838 if (GET_CODE (op
) == CONST_INT
)
2840 /* Inverse of constants */
2841 int i
= INTVAL (op
);
2842 fprintf (file
, "%d", ~i
);
2847 case 'r': /* Conditional jump where the condition is reversed. */
2848 switch (GET_CODE (op
))
2850 case EQ
: fprintf (file
, "NE"); break;
2851 case NE
: fprintf (file
, "EQ"); break;
2852 case GEU
: fprintf (file
, "LO"); break;
2853 case LTU
: fprintf (file
, "HS"); break;
2854 case GE
: fprintf (file
, "L"); break;
2855 case LT
: fprintf (file
, "GE"); break;
2856 /* Assume these have reversed operands. */
2857 case GTU
: fprintf (file
, "HS"); break;
2858 case LEU
: fprintf (file
, "LO"); break;
2859 case GT
: fprintf (file
, "GE"); break;
2860 case LE
: fprintf (file
, "L"); break;
2862 msp430_print_operand_raw (file
, op
);
2866 case 'R': /* Conditional jump where the operands are reversed. */
2867 switch (GET_CODE (op
))
2869 case GTU
: fprintf (file
, "LO"); break;
2870 case LEU
: fprintf (file
, "HS"); break;
2871 case GT
: fprintf (file
, "L"); break;
2872 case LE
: fprintf (file
, "GE"); break;
2874 msp430_print_operand_raw (file
, op
);
2878 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
2879 gcc_assert (CONST_INT_P (op
));
2880 fprintf (file
, "#%d", 1 << INTVAL (op
));
2883 switch (GET_MODE (op
))
2885 case QImode
: fprintf (file
, ".B"); return;
2886 case HImode
: fprintf (file
, ".W"); return;
2887 case PSImode
: fprintf (file
, ".A"); return;
2888 case SImode
: fprintf (file
, ".A"); return;
2893 case 'L': /* Low half. */
2894 switch (GET_CODE (op
))
2897 op
= adjust_address (op
, Pmode
, 0);
2902 op
= GEN_INT (INTVAL (op
) & 0xffff);
2906 /* If you get here, figure out a test case :-) */
2911 case 'H': /* high half */
2912 switch (GET_CODE (op
))
2915 op
= adjust_address (op
, Pmode
, 2);
2918 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 1);
2921 op
= GEN_INT (INTVAL (op
) >> 16);
2925 /* If you get here, figure out a test case :-) */
2930 switch (GET_CODE (op
))
2933 op
= adjust_address (op
, Pmode
, 3);
2936 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 2);
2939 op
= GEN_INT ((long long) INTVAL (op
) >> 32);
2943 /* If you get here, figure out a test case :-) */
2948 switch (GET_CODE (op
))
2951 op
= adjust_address (op
, Pmode
, 4);
2954 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 3);
2957 op
= GEN_INT ((long long) INTVAL (op
) >> 48);
2961 /* If you get here, figure out a test case :-) */
2967 /* This is used to turn, for example, an ADD opcode into an ADDX
2968 opcode when we're using 20-bit addresses. */
2969 if (TARGET_LARGE
|| GET_MODE (op
) == PSImode
)
2970 fprintf (file
, "X");
2971 /* We don't care which operand we use, but we want 'X' in the MD
2972 file, so we do it this way. */
2976 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
2977 if (GET_MODE (op
) == PSImode
)
2978 fprintf (file
, "X");
2982 /* Likewise, for BR -> BRA. */
2984 fprintf (file
, "A");
2988 /* Computes the offset to the top of the stack for the current frame.
2989 This has to be done here rather than in, say, msp430_expand_builtin()
2990 because builtins are expanded before the frame layout is determined. */
2991 fprintf (file
, "%d",
2992 msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, STACK_POINTER_REGNUM
)
2993 - (TARGET_LARGE
? 4 : 2));
2997 gcc_assert (GET_CODE (op
) == CONST_INT
);
3001 output_operand_lossage ("invalid operand prefix");
3005 switch (GET_CODE (op
))
3008 msp430_print_operand_raw (file
, op
);
3012 addr
= XEXP (op
, 0);
3013 msp430_print_operand_addr (file
, addr
);
3017 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTRACT
)
3020 switch (INTVAL (XEXP (op
, 2)))
3023 fprintf (file
, "#lo (");
3024 msp430_print_operand_raw (file
, XEXP (op
, 0));
3025 fprintf (file
, ")");
3029 fprintf (file
, "#hi (");
3030 msp430_print_operand_raw (file
, XEXP (op
, 0));
3031 fprintf (file
, ")");
3035 output_operand_lossage ("invalid zero extract");
3045 fprintf (file
, "#");
3046 msp430_print_operand_raw (file
, op
);
3049 case EQ
: fprintf (file
, "EQ"); break;
3050 case NE
: fprintf (file
, "NE"); break;
3051 case GEU
: fprintf (file
, "HS"); break;
3052 case LTU
: fprintf (file
, "LO"); break;
3053 case GE
: fprintf (file
, "GE"); break;
3054 case LT
: fprintf (file
, "L"); break;
3057 print_rtl (file
, op
);
3066 msp430_return_addr_rtx (int count
)
3072 ra_size
= TARGET_LARGE
? 4 : 2;
3073 if (crtl
->args
.pretend_args_size
)
3076 return gen_rtx_MEM (Pmode
, gen_rtx_PLUS (Pmode
, arg_pointer_rtx
, GEN_INT (- ra_size
)));
3080 msp430_incoming_return_addr_rtx (void)
3082 return gen_rtx_MEM (Pmode
, stack_pointer_rtx
);
3085 /* Instruction generation stuff. */
3087 /* Generate a sequence of instructions to sign-extend an HI
3088 value into an SI value. Handles the tricky case where
3089 we are overwriting the destination. */
3092 msp430x_extendhisi (rtx
* operands
)
3094 if (REGNO (operands
[0]) == REGNO (operands
[1]))
3095 /* Low word of dest == source word. */
3096 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
3099 /* Note: This sequence is approximately the same length as invoking a helper
3100 function to perform the sign-extension, as in:
3104 CALL __mspabi_srai_15
3107 but this version does not involve any function calls or using argument
3108 registers, so it reduces register pressure. */
3109 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
3111 if (REGNO (operands
[0]) + 1 == REGNO (operands
[1]))
3112 /* High word of dest == source word. */
3113 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
3115 /* No overlap between dest and source. */
3116 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
3119 /* Likewise for logical right shifts. */
3121 msp430x_logical_shift_right (rtx amount
)
3123 /* The MSP430X's logical right shift instruction - RRUM - does
3124 not use an extension word, so we cannot encode a repeat count.
3125 Try various alternatives to work around this. If the count
3126 is in a register we are stuck, hence the assert. */
3127 gcc_assert (CONST_INT_P (amount
));
3129 if (INTVAL (amount
) <= 0
3130 || INTVAL (amount
) >= 16)
3131 return "# nop logical shift.";
3133 if (INTVAL (amount
) > 0
3134 && INTVAL (amount
) < 5)
3135 return "rrum.w\t%2, %0"; /* Two bytes. */
3137 if (INTVAL (amount
) > 4
3138 && INTVAL (amount
) < 9)
3139 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
3141 /* First we logically shift right by one. Now we know
3142 that the top bit is zero and we can use the arithmetic
3143 right shift instruction to perform the rest of the shift. */
3144 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
3147 struct gcc_target targetm
= TARGET_INITIALIZER
;
3149 #include "gt-msp430.h"