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"
34 #include "hard-reg-set.h"
35 #include "insn-config.h"
36 #include "conditions.h"
38 #include "insn-attr.h"
48 #include "insn-codes.h"
52 #include "diagnostic-core.h"
55 #include "dominance.h"
61 #include "cfgcleanup.h"
63 #include "basic-block.h"
68 #include "target-def.h"
69 #include "langhooks.h"
70 #include "msp430-protos.h"
76 static void msp430_compute_frame_info (void);
80 /* Run-time Target Specification. */
84 struct GTY(()) machine_function
86 /* If set, the rest of the fields have been computed. */
88 /* Which registers need to be saved in the pro/epilogue. */
89 int need_to_save
[FIRST_PSEUDO_REGISTER
];
91 /* These fields describe the frame layout... */
93 /* 2/4 bytes for saved PC */
97 int framesize_outgoing
;
101 /* How much we adjust the stack when returning from an exception
106 /* This is our init_machine_status, as set in
107 msp_option_override. */
108 static struct machine_function
*
109 msp430_init_machine_status (void)
111 struct machine_function
*m
;
113 m
= ggc_cleared_alloc
<machine_function
> ();
118 #undef TARGET_OPTION_OVERRIDE
119 #define TARGET_OPTION_OVERRIDE msp430_option_override
121 static const char * msp430_mcu_names
[] =
123 "msp430afe221", "msp430afe222", "msp430afe223", "msp430afe231",
124 "msp430afe232", "msp430afe233", "msp430afe251", "msp430afe252",
125 "msp430afe253", "msp430c091", "msp430c092", "msp430c111",
126 "msp430c1111", "msp430c112", "msp430c1121", "msp430c1331",
127 "msp430c1351", "msp430c311s", "msp430c312", "msp430c313",
128 "msp430c314", "msp430c315", "msp430c323", "msp430c325",
129 "msp430c336", "msp430c337", "msp430c412", "msp430c413",
130 "msp430e112", "msp430e313", "msp430e315", "msp430e325",
131 "msp430e337", "msp430f110", "msp430f1101", "msp430f1101a",
132 "msp430f1111", "msp430f1111a", "msp430f112", "msp430f1121",
133 "msp430f1121a", "msp430f1122", "msp430f1132", "msp430f122",
134 "msp430f1222", "msp430f123", "msp430f1232", "msp430f133",
135 "msp430f135", "msp430f147", "msp430f1471", "msp430f148",
136 "msp430f1481", "msp430f149", "msp430f1491", "msp430f155",
137 "msp430f156", "msp430f157", "msp430f1610", "msp430f1611",
138 "msp430f1612", "msp430f167", "msp430f168", "msp430f169",
139 "msp430f2001", "msp430f2002", "msp430f2003", "msp430f2011",
140 "msp430f2012", "msp430f2013", "msp430f2101", "msp430f2111",
141 "msp430f2112", "msp430f2121", "msp430f2122", "msp430f2131",
142 "msp430f2132", "msp430f2232", "msp430f2234", "msp430f2252",
143 "msp430f2254", "msp430f2272", "msp430f2274", "msp430f233",
144 "msp430f2330", "msp430f235", "msp430f2350", "msp430f2370",
145 "msp430f2410", "msp430f247", "msp430f2471", "msp430f248",
146 "msp430f2481", "msp430f249", "msp430f2491", "msp430f412",
147 "msp430f413", "msp430f4132", "msp430f415", "msp430f4152",
148 "msp430f417", "msp430f423", "msp430f423a", "msp430f425",
149 "msp430f4250", "msp430f425a", "msp430f4260", "msp430f427",
150 "msp430f4270", "msp430f427a", "msp430f435", "msp430f4351",
151 "msp430f436", "msp430f4361", "msp430f437", "msp430f4371",
152 "msp430f438", "msp430f439", "msp430f447", "msp430f448",
153 "msp430f4481", "msp430f449", "msp430f4491", "msp430f477",
154 "msp430f478", "msp430f4783", "msp430f4784", "msp430f479",
155 "msp430f4793", "msp430f4794", "msp430fe423", "msp430fe4232",
156 "msp430fe423a", "msp430fe4242", "msp430fe425", "msp430fe4252",
157 "msp430fe425a", "msp430fe427", "msp430fe4272", "msp430fe427a",
158 "msp430fg4250", "msp430fg4260", "msp430fg4270", "msp430fg437",
159 "msp430fg438", "msp430fg439", "msp430fg477", "msp430fg478",
160 "msp430fg479", "msp430fw423", "msp430fw425", "msp430fw427",
161 "msp430fw428", "msp430fw429", "msp430g2001", "msp430g2101",
162 "msp430g2102", "msp430g2111", "msp430g2112", "msp430g2113",
163 "msp430g2121", "msp430g2131", "msp430g2132", "msp430g2152",
164 "msp430g2153", "msp430g2201", "msp430g2202", "msp430g2203",
165 "msp430g2210", "msp430g2211", "msp430g2212", "msp430g2213",
166 "msp430g2221", "msp430g2230", "msp430g2231", "msp430g2232",
167 "msp430g2233", "msp430g2252", "msp430g2253", "msp430g2302",
168 "msp430g2303", "msp430g2312", "msp430g2313", "msp430g2332",
169 "msp430g2333", "msp430g2352", "msp430g2353", "msp430g2402",
170 "msp430g2403", "msp430g2412", "msp430g2413", "msp430g2432",
171 "msp430g2433", "msp430g2444", "msp430g2452", "msp430g2453",
172 "msp430g2513", "msp430g2533", "msp430g2544", "msp430g2553",
173 "msp430g2744", "msp430g2755", "msp430g2855", "msp430g2955",
174 "msp430i2020", "msp430i2021", "msp430i2030", "msp430i2031",
175 "msp430i2040", "msp430i2041", "msp430l092", "msp430p112",
176 "msp430p313", "msp430p315", "msp430p315s", "msp430p325",
177 "msp430p337", "msp430tch5e"
180 /* Generate a C preprocessor symbol based upon the MCU selected by the user.
181 If a specific MCU has not been selected then return a generic symbol instead. */
184 msp430_mcu_name (void)
189 static char mcu_name
[64];
191 snprintf (mcu_name
, sizeof (mcu_name
) - 1, "__%s__", target_mcu
);
192 for (i
= strlen (mcu_name
); i
--;)
193 mcu_name
[i
] = TOUPPER (mcu_name
[i
]);
197 return msp430x
? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
201 msp430_option_override (void)
203 init_machine_status
= msp430_init_machine_status
;
207 if (strcasecmp (target_cpu
, "msp430x") == 0)
209 else /* target_cpu == "msp430" - already handled by the front end. */
212 /* Note - the front end has already ensured at most
213 one of target_cpu and target_mcu will be set. */
218 /* If we are given an MCU name, we assume that it supports 430X.
219 Then we check to see if it is one of the known MCUs that only
223 for (i
= ARRAY_SIZE (msp430_mcu_names
); i
--;)
224 if (strcasecmp (msp430_mcu_names
[i
], target_mcu
) == 0)
229 /* It is not an error if we do not match the MCU name. There are
233 if (TARGET_LARGE
&& !msp430x
)
234 error ("-mlarge requires a 430X-compatible -mmcu=");
236 if (msp430_code_region
== UPPER
&& ! msp430x
)
237 error ("-mcode-region=upper requires 430X-compatible cpu");
238 if (msp430_data_region
== UPPER
&& ! msp430x
)
239 error ("-mdata-region=upper requires 430X-compatible cpu");
241 if (flag_exceptions
|| flag_non_call_exceptions
242 || flag_unwind_tables
|| flag_asynchronous_unwind_tables
)
243 flag_omit_frame_pointer
= false;
245 flag_omit_frame_pointer
= true;
247 /* This is a hack to work around a problem with the newlib build
248 mechanism. Newlib always appends CFLAGS to the end of the GCC
249 command line and always sets -O2 in CFLAGS. Thus it is not
250 possible to build newlib with -Os enabled. Until now... */
251 if (TARGET_OPT_SPACE
&& optimize
< 3)
255 #undef TARGET_SCALAR_MODE_SUPPORTED_P
256 #define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
259 msp430_scalar_mode_supported_p (machine_mode m
)
261 if (m
== PSImode
&& msp430x
)
267 return default_scalar_mode_supported_p (m
);
274 #undef TARGET_MS_BITFIELD_LAYOUT_P
275 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
278 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED
)
287 /* Implements HARD_REGNO_NREGS. MSP430X registers can hold a single
288 PSImode value, but not an SImode value. */
290 msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED
,
293 if (mode
== PSImode
&& msp430x
)
295 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
299 /* Implements HARD_REGNO_NREGS_HAS_PADDING. */
301 msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED
,
304 if (mode
== PSImode
&& msp430x
)
306 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
310 /* Implements HARD_REGNO_NREGS_WITH_PADDING. */
312 msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED
,
317 return msp430_hard_regno_nregs (regno
, mode
);
320 /* Implements HARD_REGNO_MODE_OK. */
322 msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED
,
325 return regno
<= (ARG_POINTER_REGNUM
- msp430_hard_regno_nregs (regno
, mode
));
328 /* Implements MODES_TIEABLE_P. */
330 msp430_modes_tieable_p (machine_mode mode1
, machine_mode mode2
)
332 if ((mode1
== PSImode
|| mode2
== SImode
)
333 || (mode1
== SImode
|| mode2
== PSImode
))
336 return ((GET_MODE_CLASS (mode1
) == MODE_FLOAT
337 || GET_MODE_CLASS (mode1
) == MODE_COMPLEX_FLOAT
)
338 == (GET_MODE_CLASS (mode2
) == MODE_FLOAT
339 || GET_MODE_CLASS (mode2
) == MODE_COMPLEX_FLOAT
));
342 #undef TARGET_FRAME_POINTER_REQUIRED
343 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
346 msp430_frame_pointer_required (void)
351 #undef TARGET_CAN_ELIMINATE
352 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
355 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED
,
356 const int to_reg ATTRIBUTE_UNUSED
)
361 /* Implements INITIAL_ELIMINATION_OFFSET. */
363 msp430_initial_elimination_offset (int from
, int to
)
365 int rv
= 0; /* As if arg to arg. */
367 msp430_compute_frame_info ();
371 case STACK_POINTER_REGNUM
:
372 rv
+= cfun
->machine
->framesize_outgoing
;
373 rv
+= cfun
->machine
->framesize_locals
;
375 case FRAME_POINTER_REGNUM
:
376 rv
+= cfun
->machine
->framesize_regs
;
377 /* Allow for the saved return address. */
378 rv
+= (TARGET_LARGE
? 4 : 2);
379 /* NB/ No need to allow for crtl->args.pretend_args_size.
380 GCC does that for us. */
388 case FRAME_POINTER_REGNUM
:
389 /* Allow for the fall through above. */
390 rv
-= (TARGET_LARGE
? 4 : 2);
391 rv
-= cfun
->machine
->framesize_regs
;
392 case ARG_POINTER_REGNUM
:
401 /* Named Address Space support */
404 /* Return the appropriate mode for a named address pointer. */
405 #undef TARGET_ADDR_SPACE_POINTER_MODE
406 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
407 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
408 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
411 msp430_addr_space_pointer_mode (addr_space_t addrspace
)
416 case ADDR_SPACE_GENERIC
:
418 case ADDR_SPACE_NEAR
:
425 /* Function pointers are stored in unwind_word sized
426 variables, so make sure that unwind_word is big enough. */
427 #undef TARGET_UNWIND_WORD_MODE
428 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
431 msp430_unwind_word_mode (void)
433 return TARGET_LARGE
? PSImode
: HImode
;
436 /* Determine if one named address space is a subset of another. */
437 #undef TARGET_ADDR_SPACE_SUBSET_P
438 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
440 msp430_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
442 if (subset
== superset
)
445 return (subset
!= ADDR_SPACE_FAR
&& superset
== ADDR_SPACE_FAR
);
448 #undef TARGET_ADDR_SPACE_CONVERT
449 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
450 /* Convert from one address space to another. */
452 msp430_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
454 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
455 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
458 if (to_as
!= ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_FAR
)
460 /* This is unpredictable, as we're truncating off usable address
464 return gen_rtx_CONST (HImode
, op
);
466 result
= gen_reg_rtx (HImode
);
467 emit_insn (gen_truncpsihi2 (result
, op
));
470 else if (to_as
== ADDR_SPACE_FAR
&& from_as
!= ADDR_SPACE_FAR
)
472 /* This always works. */
475 return gen_rtx_CONST (PSImode
, op
);
477 result
= gen_reg_rtx (PSImode
);
478 emit_insn (gen_zero_extendhipsi2 (result
, op
));
485 /* Stack Layout and Calling Conventions. */
487 /* For each function, we list the gcc version and the TI version on
488 each line, where we're converting the function names. */
489 static char const * const special_convention_function_names
[] =
491 "__muldi3", "__mspabi_mpyll",
492 "__udivdi3", "__mspabi_divull",
493 "__umoddi3", "__mspabi_remull",
494 "__divdi3", "__mspabi_divlli",
495 "__moddi3", "__mspabi_remlli",
499 "__adddf3", "__mspabi_addd",
500 "__subdf3", "__mspabi_subd",
501 "__muldf3", "__mspabi_mpyd",
502 "__divdf3", "__mspabi_divd",
507 /* TRUE if the function passed is a "speical" function. Special
508 functions pass two DImode parameters in registers. */
510 msp430_special_register_convention_p (const char *name
)
514 for (i
= 0; special_convention_function_names
[i
]; i
++)
515 if (! strcmp (name
, special_convention_function_names
[i
]))
521 #undef TARGET_FUNCTION_VALUE_REGNO_P
522 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
525 msp430_function_value_regno_p (unsigned int regno
)
531 #undef TARGET_FUNCTION_VALUE
532 #define TARGET_FUNCTION_VALUE msp430_function_value
535 msp430_function_value (const_tree ret_type
,
536 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
537 bool outgoing ATTRIBUTE_UNUSED
)
539 return gen_rtx_REG (TYPE_MODE (ret_type
), 12);
542 #undef TARGET_LIBCALL_VALUE
543 #define TARGET_LIBCALL_VALUE msp430_libcall_value
546 msp430_libcall_value (machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
548 return gen_rtx_REG (mode
, 12);
551 /* Implements INIT_CUMULATIVE_ARGS. */
553 msp430_init_cumulative_args (CUMULATIVE_ARGS
*ca
,
554 tree fntype ATTRIBUTE_UNUSED
,
555 rtx libname ATTRIBUTE_UNUSED
,
556 tree fndecl ATTRIBUTE_UNUSED
,
557 int n_named_args ATTRIBUTE_UNUSED
)
560 memset (ca
, 0, sizeof(*ca
));
565 fname
= IDENTIFIER_POINTER (DECL_NAME (fndecl
));
567 fname
= XSTR (libname
, 0);
571 if (fname
&& msp430_special_register_convention_p (fname
))
575 /* Helper function for argument passing; this function is the common
576 code that determines where an argument will be passed. */
578 msp430_evaluate_arg (cumulative_args_t cap
,
580 const_tree type ATTRIBUTE_UNUSED
,
583 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
584 int nregs
= GET_MODE_SIZE (mode
);
596 nregs
= (nregs
+ 1) / 2;
600 /* Function is passed two DImode operands, in R8:R11 and
610 for (i
= 0; i
< 4; i
++)
611 if (! ca
->reg_used
[i
])
614 ca
->start_reg
= CA_FIRST_REG
+ i
;
619 for (i
= 0; i
< 3; i
++)
620 if (! ca
->reg_used
[i
] && ! ca
->reg_used
[i
+ 1])
623 ca
->start_reg
= CA_FIRST_REG
+ i
;
626 if (! ca
->reg_used
[3] && ca
->can_split
)
630 ca
->start_reg
= CA_FIRST_REG
+ 3;
637 if (! ca
->reg_used
[0]
638 && ! ca
->reg_used
[1]
639 && ! ca
->reg_used
[2]
640 && ! ca
->reg_used
[3])
643 ca
->start_reg
= CA_FIRST_REG
;
650 #undef TARGET_PROMOTE_PROTOTYPES
651 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
654 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED
)
659 #undef TARGET_FUNCTION_ARG
660 #define TARGET_FUNCTION_ARG msp430_function_arg
663 msp430_function_arg (cumulative_args_t cap
,
668 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
670 msp430_evaluate_arg (cap
, mode
, type
, named
);
673 return gen_rtx_REG (mode
, ca
->start_reg
);
678 #undef TARGET_ARG_PARTIAL_BYTES
679 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
682 msp430_arg_partial_bytes (cumulative_args_t cap
,
687 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
689 msp430_evaluate_arg (cap
, mode
, type
, named
);
691 if (ca
->reg_count
&& ca
->mem_count
)
692 return ca
->reg_count
* UNITS_PER_WORD
;
697 #undef TARGET_PASS_BY_REFERENCE
698 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
701 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED
,
704 bool named ATTRIBUTE_UNUSED
)
706 return (mode
== BLKmode
707 || (type
&& TREE_CODE (type
) == RECORD_TYPE
)
708 || (type
&& TREE_CODE (type
) == UNION_TYPE
));
711 #undef TARGET_CALLEE_COPIES
712 #define TARGET_CALLEE_COPIES msp430_callee_copies
715 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED
,
716 machine_mode mode ATTRIBUTE_UNUSED
,
717 const_tree type ATTRIBUTE_UNUSED
,
718 bool named ATTRIBUTE_UNUSED
)
723 #undef TARGET_FUNCTION_ARG_ADVANCE
724 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
727 msp430_function_arg_advance (cumulative_args_t cap
,
732 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
735 msp430_evaluate_arg (cap
, mode
, type
, named
);
737 if (ca
->start_reg
>= CA_FIRST_REG
)
738 for (i
= 0; i
< ca
->reg_count
; i
++)
739 ca
->reg_used
[i
+ ca
->start_reg
- CA_FIRST_REG
] = 1;
744 #undef TARGET_FUNCTION_ARG_BOUNDARY
745 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
748 msp430_function_arg_boundary (machine_mode mode
, const_tree type
)
751 && int_size_in_bytes (type
) > 1)
753 if (GET_MODE_BITSIZE (mode
) > 8)
758 #undef TARGET_RETURN_IN_MEMORY
759 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
762 msp430_return_in_memory (const_tree ret_type
, const_tree fntype ATTRIBUTE_UNUSED
)
764 machine_mode mode
= TYPE_MODE (ret_type
);
767 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == RECORD_TYPE
)
768 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == UNION_TYPE
))
771 if (GET_MODE_SIZE (mode
) > 8)
777 #undef TARGET_GET_RAW_ARG_MODE
778 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
781 msp430_get_raw_arg_mode (int regno
)
783 return (regno
== ARG_POINTER_REGNUM
) ? VOIDmode
: Pmode
;
786 #undef TARGET_GET_RAW_RESULT_MODE
787 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
790 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED
)
795 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
796 #define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
798 #include "gimplify.h"
799 #include "gimple-expr.h"
802 msp430_gimplify_va_arg_expr (tree valist
, tree type
, gimple_seq
*pre_p
,
805 tree addr
, t
, type_size
, rounded_size
, valist_tmp
;
806 unsigned HOST_WIDE_INT align
, boundary
;
809 indirect
= pass_by_reference (NULL
, TYPE_MODE (type
), type
, false);
811 type
= build_pointer_type (type
);
813 align
= PARM_BOUNDARY
/ BITS_PER_UNIT
;
814 boundary
= targetm
.calls
.function_arg_boundary (TYPE_MODE (type
), type
);
816 /* When we align parameter on stack for caller, if the parameter
817 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
818 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
820 if (boundary
> MAX_SUPPORTED_STACK_ALIGNMENT
)
821 boundary
= MAX_SUPPORTED_STACK_ALIGNMENT
;
823 boundary
/= BITS_PER_UNIT
;
825 /* Hoist the valist value into a temporary for the moment. */
826 valist_tmp
= get_initialized_tmp_var (valist
, pre_p
, NULL
);
828 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
829 requires greater alignment, we must perform dynamic alignment. */
831 && !integer_zerop (TYPE_SIZE (type
)))
833 /* FIXME: This is where this function diverts from targhooks.c:
834 std_gimplify_va_arg_expr(). It works, but I do not know why... */
835 if (! POINTER_TYPE_P (type
))
837 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
838 fold_build_pointer_plus_hwi (valist_tmp
, boundary
- 1));
839 gimplify_and_add (t
, pre_p
);
841 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
842 fold_build2 (BIT_AND_EXPR
, TREE_TYPE (valist
),
844 build_int_cst (TREE_TYPE (valist
), -boundary
)));
845 gimplify_and_add (t
, pre_p
);
851 /* If the actual alignment is less than the alignment of the type,
852 adjust the type accordingly so that we don't assume strict alignment
853 when dereferencing the pointer. */
854 boundary
*= BITS_PER_UNIT
;
855 if (boundary
< TYPE_ALIGN (type
))
857 type
= build_variant_type_copy (type
);
858 TYPE_ALIGN (type
) = boundary
;
861 /* Compute the rounded size of the type. */
862 type_size
= size_in_bytes (type
);
863 rounded_size
= round_up (type_size
, align
);
865 /* Reduce rounded_size so it's sharable with the postqueue. */
866 gimplify_expr (&rounded_size
, pre_p
, post_p
, is_gimple_val
, fb_rvalue
);
871 /* Compute new value for AP. */
872 t
= fold_build_pointer_plus (valist_tmp
, rounded_size
);
873 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist
, t
);
874 gimplify_and_add (t
, pre_p
);
876 addr
= fold_convert (build_pointer_type (type
), addr
);
879 addr
= build_va_arg_indirect_ref (addr
);
881 addr
= build_va_arg_indirect_ref (addr
);
886 /* Addressing Modes */
888 #undef TARGET_LEGITIMATE_ADDRESS_P
889 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
892 reg_ok_for_addr (rtx r
, bool strict
)
896 if (strict
&& rn
>= FIRST_PSEUDO_REGISTER
)
897 rn
= reg_renumber
[rn
];
898 if (strict
&& 0 <= rn
&& rn
< FIRST_PSEUDO_REGISTER
)
906 msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED
,
907 rtx x ATTRIBUTE_UNUSED
,
908 bool strict ATTRIBUTE_UNUSED
)
910 switch (GET_CODE (x
))
916 if (REG_P (XEXP (x
, 0)))
918 if (GET_MODE (x
) != GET_MODE (XEXP (x
, 0)))
920 if (!reg_ok_for_addr (XEXP (x
, 0), strict
))
922 switch (GET_CODE (XEXP (x
, 1)))
935 if (!reg_ok_for_addr (x
, strict
))
948 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
949 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
952 msp430_addr_space_legitimate_address_p (machine_mode mode
,
955 addr_space_t as ATTRIBUTE_UNUSED
)
957 return msp430_legitimate_address_p (mode
, x
, strict
);
960 #undef TARGET_ASM_INTEGER
961 #define TARGET_ASM_INTEGER msp430_asm_integer
963 msp430_asm_integer (rtx x
, unsigned int size
, int aligned_p
)
965 int c
= GET_CODE (x
);
967 if (size
== 3 && GET_MODE (x
) == PSImode
)
973 if (c
== SYMBOL_REF
|| c
== CONST
|| c
== LABEL_REF
|| c
== CONST_INT
974 || c
== PLUS
|| c
== MINUS
)
976 fprintf (asm_out_file
, "\t.long\t");
977 output_addr_const (asm_out_file
, x
);
978 fputc ('\n', asm_out_file
);
983 return default_assemble_integer (x
, size
, aligned_p
);
986 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
987 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra
989 msp430_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED
, rtx x
)
995 #undef TARGET_LEGITIMATE_CONSTANT_P
996 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
999 msp430_legitimate_constant (machine_mode mode
, rtx x
)
1001 return ! CONST_INT_P (x
)
1003 /* GCC does not know the width of the PSImode, so make
1004 sure that it does not try to use a constant value that
1006 || (INTVAL (x
) < (1 << 20) && INTVAL (x
) >= (-1 << 20));
1010 #undef TARGET_RTX_COSTS
1011 #define TARGET_RTX_COSTS msp430_rtx_costs
1013 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED
,
1015 int outer_code ATTRIBUTE_UNUSED
,
1016 int opno ATTRIBUTE_UNUSED
,
1018 bool speed ATTRIBUTE_UNUSED
)
1023 if (GET_MODE (x
) == SImode
&& outer_code
== SET
)
1025 *total
= COSTS_N_INSNS (4);
1034 *total
= COSTS_N_INSNS (100);
1042 /* Function Entry and Exit */
1044 /* The MSP430 call frame looks like this:
1047 +--------------------+
1051 +--------------------+ <-- "arg pointer"
1053 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
1055 +--------------------+
1056 | SR if this func has|
1057 | been called via an |
1059 +--------------------+ <-- SP before prologue, also AP
1061 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
1063 +--------------------+ <-- "frame pointer"
1067 +--------------------+
1071 +--------------------+ <-- SP during function
1076 /* We use this to wrap all emitted insns in the prologue, so they get
1077 the "frame-related" (/f) flag set. */
1081 RTX_FRAME_RELATED_P (x
) = 1;
1085 /* This is the one spot that decides if a register is to be saved and
1086 restored in the prologue/epilogue. */
1088 msp430_preserve_reg_p (int regno
)
1090 /* PC, SP, SR, and the constant generator. */
1094 /* FIXME: add interrupt, EH, etc. */
1095 if (crtl
->calls_eh_return
)
1098 /* Shouldn't be more than the above, but just in case... */
1099 if (fixed_regs
[regno
])
1102 /* Interrupt handlers save all registers they use, even
1103 ones which are call saved. If they call other functions
1104 then *every* register is saved. */
1105 if (msp430_is_interrupt_func ())
1106 return ! crtl
->is_leaf
|| df_regs_ever_live_p (regno
);
1108 if (!call_used_regs
[regno
]
1109 && df_regs_ever_live_p (regno
))
1115 /* Compute all the frame-related fields in our machine_function
1118 msp430_compute_frame_info (void)
1122 cfun
->machine
->computed
= 1;
1123 cfun
->machine
->framesize_regs
= 0;
1124 cfun
->machine
->framesize_locals
= get_frame_size ();
1125 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
1127 for (i
= 0; i
< ARG_POINTER_REGNUM
; i
++)
1128 if (msp430_preserve_reg_p (i
))
1130 cfun
->machine
->need_to_save
[i
] = 1;
1131 cfun
->machine
->framesize_regs
+= (TARGET_LARGE
? 4 : 2);
1134 cfun
->machine
->need_to_save
[i
] = 0;
1136 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
1137 cfun
->machine
->framesize_locals
++;
1139 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
1140 + cfun
->machine
->framesize_locals
1141 + cfun
->machine
->framesize_outgoing
);
1144 /* Attribute Handling. */
1146 const char * const ATTR_INTR
= "interrupt";
1147 const char * const ATTR_WAKEUP
= "wakeup";
1148 const char * const ATTR_NAKED
= "naked";
1149 const char * const ATTR_REENT
= "reentrant";
1150 const char * const ATTR_CRIT
= "critical";
1151 const char * const ATTR_LOWER
= "lower";
1152 const char * const ATTR_UPPER
= "upper";
1153 const char * const ATTR_EITHER
= "either";
1156 has_attr (const char * attr
, tree decl
)
1158 if (decl
== NULL_TREE
)
1160 return lookup_attribute (attr
, DECL_ATTRIBUTES (decl
)) != NULL_TREE
;
1164 is_interrupt_func (tree decl
= current_function_decl
)
1166 return has_attr (ATTR_INTR
, decl
);
1169 /* Returns true if the current function has the "interrupt" attribute. */
1172 msp430_is_interrupt_func (void)
1174 return is_interrupt_func (current_function_decl
);
1178 is_wakeup_func (tree decl
= current_function_decl
)
1180 return is_interrupt_func (decl
) && has_attr (ATTR_WAKEUP
, decl
);
1184 is_naked_func (tree decl
= current_function_decl
)
1186 return has_attr (ATTR_NAKED
, decl
);
1190 is_reentrant_func (tree decl
= current_function_decl
)
1192 return has_attr (ATTR_REENT
, decl
);
1196 is_critical_func (tree decl
= current_function_decl
)
1198 return has_attr (ATTR_CRIT
, decl
);
1201 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
1202 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS msp430_allocate_stack_slots_for_args
1205 msp430_allocate_stack_slots_for_args (void)
1207 /* Naked functions should not allocate stack slots for arguments. */
1208 return ! is_naked_func ();
1211 /* Verify MSP430 specific attributes. */
1212 #define TREE_NAME_EQ(NAME, STR) (strcmp (IDENTIFIER_POINTER (NAME), (STR)) == 0)
1215 msp430_attr (tree
* node
,
1218 int flags ATTRIBUTE_UNUSED
,
1219 bool * no_add_attrs
)
1221 gcc_assert (DECL_P (* node
));
1225 gcc_assert (TREE_NAME_EQ (name
, ATTR_INTR
));
1227 tree value
= TREE_VALUE (args
);
1229 switch (TREE_CODE (value
))
1232 if ( strcmp (TREE_STRING_POINTER (value
), "reset")
1233 && strcmp (TREE_STRING_POINTER (value
), "nmi")
1234 && strcmp (TREE_STRING_POINTER (value
), "watchdog"))
1235 /* Allow the attribute to be added - the linker script
1236 being used may still recognise this name. */
1237 warning (OPT_Wattributes
,
1238 "unrecognised interrupt vector argument of %qE attribute",
1243 if (wi::gtu_p (value
, 63))
1244 /* Allow the attribute to be added - the linker script
1245 being used may still recognise this value. */
1246 warning (OPT_Wattributes
,
1247 "numeric argument of %qE attribute must be in range 0..63",
1252 warning (OPT_Wattributes
,
1253 "argument of %qE attribute is not a string constant or number",
1255 *no_add_attrs
= true;
1260 const char * message
= NULL
;
1262 if (TREE_CODE (* node
) != FUNCTION_DECL
)
1264 message
= "%qE attribute only applies to functions";
1266 else if (TREE_NAME_EQ (name
, ATTR_INTR
))
1268 if (TREE_CODE (TREE_TYPE (* node
)) == FUNCTION_TYPE
1269 && ! VOID_TYPE_P (TREE_TYPE (TREE_TYPE (* node
))))
1270 message
= "interrupt handlers must be void";
1272 else if (TREE_NAME_EQ (name
, ATTR_REENT
))
1274 if (is_naked_func (* node
))
1275 message
= "naked functions cannot be reentrant";
1276 else if (is_critical_func (* node
))
1277 message
= "critical functions cannot be reentrant";
1279 else if (TREE_NAME_EQ (name
, ATTR_CRIT
))
1281 if (is_naked_func (* node
))
1282 message
= "naked functions cannot be critical";
1283 else if (is_reentrant_func (* node
))
1284 message
= "reentranct functions cannot be critical";
1286 else if (TREE_NAME_EQ (name
, ATTR_NAKED
))
1288 if (is_critical_func (* node
))
1289 message
= "critical functions cannot be naked";
1290 else if (is_reentrant_func (* node
))
1291 message
= "reentrant functions cannot be naked";
1296 warning (OPT_Wattributes
, message
, name
);
1297 * no_add_attrs
= true;
1304 msp430_section_attr (tree
* node
,
1307 int flags ATTRIBUTE_UNUSED
,
1308 bool * no_add_attrs ATTRIBUTE_UNUSED
)
1310 gcc_assert (DECL_P (* node
));
1311 gcc_assert (args
== NULL
);
1313 const char * message
= NULL
;
1315 if (TREE_NAME_EQ (name
, ATTR_UPPER
))
1317 if (has_attr (ATTR_LOWER
, * node
))
1318 message
= "already marked with 'lower' attribute";
1319 else if (has_attr (ATTR_EITHER
, * node
))
1320 message
= "already marked with 'either' attribute";
1322 message
= "upper attribute needs a 430X cpu";
1324 else if (TREE_NAME_EQ (name
, ATTR_LOWER
))
1326 if (has_attr (ATTR_UPPER
, * node
))
1327 message
= "already marked with 'upper' attribute";
1328 else if (has_attr (ATTR_EITHER
, * node
))
1329 message
= "already marked with 'either' attribute";
1333 gcc_assert (TREE_NAME_EQ (name
, ATTR_EITHER
));
1335 if (has_attr (ATTR_LOWER
, * node
))
1336 message
= "already marked with 'lower' attribute";
1337 else if (has_attr (ATTR_UPPER
, * node
))
1338 message
= "already marked with 'upper' attribute";
1343 warning (OPT_Wattributes
, message
, name
);
1344 * no_add_attrs
= true;
1350 #undef TARGET_ATTRIBUTE_TABLE
1351 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
1353 /* Table of MSP430-specific attributes. */
1354 const struct attribute_spec msp430_attribute_table
[] =
1356 /* Name min_num_args type_req, affects_type_identity
1357 max_num_args, fn_type_req
1358 decl_req handler. */
1359 { ATTR_INTR
, 0, 1, true, false, false, msp430_attr
, false },
1360 { ATTR_NAKED
, 0, 0, true, false, false, msp430_attr
, false },
1361 { ATTR_REENT
, 0, 0, true, false, false, msp430_attr
, false },
1362 { ATTR_CRIT
, 0, 0, true, false, false, msp430_attr
, false },
1363 { ATTR_WAKEUP
, 0, 0, true, false, false, msp430_attr
, false },
1365 { ATTR_LOWER
, 0, 0, true, false, false, msp430_section_attr
, false },
1366 { ATTR_UPPER
, 0, 0, true, false, false, msp430_section_attr
, false },
1367 { ATTR_EITHER
, 0, 0, true, false, false, msp430_section_attr
, false },
1369 { NULL
, 0, 0, false, false, false, NULL
, false }
1372 #undef TARGET_ASM_FUNCTION_PROLOGUE
1373 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
1376 msp430_start_function (FILE *outfile
, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED
)
1380 fprintf (outfile
, "; start of function\n");
1382 if (DECL_ATTRIBUTES (current_function_decl
) != NULL_TREE
)
1384 fprintf (outfile
, "; attributes: ");
1385 if (is_naked_func ())
1386 fprintf (outfile
, "naked ");
1387 if (msp430_is_interrupt_func ())
1388 fprintf (outfile
, "interrupt ");
1389 if (is_reentrant_func ())
1390 fprintf (outfile
, "reentrant ");
1391 if (is_critical_func ())
1392 fprintf (outfile
, "critical ");
1393 if (is_wakeup_func ())
1394 fprintf (outfile
, "wakeup ");
1395 fprintf (outfile
, "\n");
1398 fprintf (outfile
, "; framesize_regs: %d\n", cfun
->machine
->framesize_regs
);
1399 fprintf (outfile
, "; framesize_locals: %d\n", cfun
->machine
->framesize_locals
);
1400 fprintf (outfile
, "; framesize_outgoing: %d\n", cfun
->machine
->framesize_outgoing
);
1401 fprintf (outfile
, "; framesize: %d\n", cfun
->machine
->framesize
);
1402 fprintf (outfile
, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, FRAME_POINTER_REGNUM
));
1403 fprintf (outfile
, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM
, STACK_POINTER_REGNUM
));
1406 fprintf (outfile
, "; saved regs:");
1407 for (r
= 0; r
< ARG_POINTER_REGNUM
; r
++)
1408 if (cfun
->machine
->need_to_save
[r
])
1410 fprintf (outfile
, " %s", reg_names
[r
]);
1414 fprintf (outfile
, "(none)");
1415 fprintf (outfile
, "\n");
1418 /* Common code to change the stack pointer. */
1420 increment_stack (HOST_WIDE_INT amount
)
1423 rtx sp
= stack_pointer_rtx
;
1430 inc
= GEN_INT (- amount
);
1432 F (emit_insn (gen_subpsi3 (sp
, sp
, inc
)));
1434 F (emit_insn (gen_subhi3 (sp
, sp
, inc
)));
1438 inc
= GEN_INT (amount
);
1440 emit_insn (gen_addpsi3 (sp
, sp
, inc
));
1442 emit_insn (gen_addhi3 (sp
, sp
, inc
));
1447 msp430_start_function (FILE *file
, const char *name
, tree decl
)
1451 int_attr
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl
));
1452 if (int_attr
!= NULL_TREE
)
1454 tree intr_vector
= TREE_VALUE (int_attr
);
1456 if (intr_vector
!= NULL_TREE
)
1460 intr_vector
= TREE_VALUE (intr_vector
);
1462 /* The interrupt attribute has a vector value. Turn this into a
1463 section name, switch to that section and put the address of
1464 the current function into that vector slot. Note msp430_attr()
1465 has already verified the vector name for us. */
1466 if (TREE_CODE (intr_vector
) == STRING_CST
)
1467 sprintf (buf
, "__interrupt_vector_%.80s",
1468 TREE_STRING_POINTER (intr_vector
));
1469 else /* TREE_CODE (intr_vector) == INTEGER_CST */
1470 sprintf (buf
, "__interrupt_vector_%u",
1471 (unsigned int) TREE_INT_CST_LOW (intr_vector
));
1473 switch_to_section (get_section (buf
, SECTION_CODE
, decl
));
1474 fputs ("\t.word\t", file
);
1475 assemble_name (file
, name
);
1481 switch_to_section (function_section (decl
));
1482 ASM_OUTPUT_FUNCTION_LABEL (file
, name
, decl
);
1485 static const char * const lower_prefix
= ".lower";
1486 static const char * const upper_prefix
= ".upper";
1487 static const char * const either_prefix
= ".either";
1489 /* Generate a prefix for a section name, based upon
1490 the region into which the object should be placed. */
1493 gen_prefix (tree decl
)
1495 if (DECL_ONE_ONLY (decl
))
1498 /* If the user has specified a particular section then do not use any prefix. */
1499 if (has_attr ("section", decl
))
1502 /* If the object has __attribute__((lower)) then use the ".lower." prefix. */
1503 if (has_attr (ATTR_LOWER
, decl
))
1504 return lower_prefix
;
1506 /* If we are compiling for the MSP430 then we do not support the upper region. */
1510 if (has_attr (ATTR_UPPER
, decl
))
1511 return upper_prefix
;
1513 if (has_attr (ATTR_EITHER
, decl
))
1514 return either_prefix
;
1516 if (TREE_CODE (decl
) == FUNCTION_DECL
)
1518 if (msp430_code_region
== LOWER
)
1519 return lower_prefix
;
1521 if (msp430_code_region
== UPPER
)
1522 return upper_prefix
;
1524 if (msp430_code_region
== EITHER
)
1525 return either_prefix
;
1529 if (msp430_data_region
== LOWER
)
1530 return lower_prefix
;
1532 if (msp430_data_region
== UPPER
)
1533 return upper_prefix
;
1535 if (msp430_data_region
== EITHER
)
1536 return either_prefix
;
1542 #undef TARGET_ASM_SELECT_SECTION
1543 #define TARGET_ASM_SELECT_SECTION msp430_select_section
1546 msp430_select_section (tree decl
, int reloc
, unsigned HOST_WIDE_INT align
)
1548 gcc_assert (decl
!= NULL_TREE
);
1550 if (TREE_CODE (decl
) == STRING_CST
1551 || TREE_CODE (decl
) == CONSTRUCTOR
1552 || TREE_CODE (decl
) == INTEGER_CST
1553 || TREE_CODE (decl
) == VECTOR_CST
1554 || TREE_CODE (decl
) == COMPLEX_CST
)
1555 return default_select_section (decl
, reloc
, align
);
1557 /* In large mode we must make sure that interrupt handlers are put into
1558 low memory as the vector table only accepts 16-bit addresses. */
1559 if (TARGET_LARGE
&& TREE_CODE (decl
) == FUNCTION_DECL
&& is_interrupt_func (decl
))
1560 return get_section (".lowtext", SECTION_CODE
| SECTION_WRITE
, decl
);
1562 const char * prefix
= gen_prefix (decl
);
1565 if (TREE_CODE (decl
) == FUNCTION_DECL
)
1566 return text_section
;
1568 return default_select_section (decl
, reloc
, align
);
1572 switch (categorize_decl_for_section (decl
, reloc
))
1574 case SECCAT_TEXT
: sec
= ".text"; break;
1575 case SECCAT_DATA
: sec
= ".data"; break;
1576 case SECCAT_BSS
: sec
= ".bss"; break;
1577 case SECCAT_RODATA
: sec
= ".rodata"; break;
1579 case SECCAT_RODATA_MERGE_STR
:
1580 case SECCAT_RODATA_MERGE_STR_INIT
:
1581 case SECCAT_RODATA_MERGE_CONST
:
1582 case SECCAT_SRODATA
:
1583 case SECCAT_DATA_REL
:
1584 case SECCAT_DATA_REL_LOCAL
:
1585 case SECCAT_DATA_REL_RO
:
1586 case SECCAT_DATA_REL_RO_LOCAL
:
1591 return default_select_section (decl
, reloc
, align
);
1597 const char * dec_name
= DECL_SECTION_NAME (decl
);
1598 char * name
= ACONCAT ((prefix
, sec
, dec_name
, NULL
));
1600 return get_named_section (decl
, name
, 0);
1603 #undef TARGET_ASM_FUNCTION_SECTION
1604 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
1607 msp430_function_section (tree decl
, enum node_frequency freq
, bool startup
, bool exit
)
1611 gcc_assert (DECL_SECTION_NAME (decl
) != NULL
);
1612 name
= DECL_SECTION_NAME (decl
);
1614 const char * prefix
= gen_prefix (decl
);
1616 || strncmp (name
, prefix
, strlen (prefix
)) == 0)
1617 return default_function_section (decl
, freq
, startup
, exit
);
1619 name
= ACONCAT ((prefix
, name
, NULL
));
1620 return get_named_section (decl
, name
, 0);
1623 #undef TARGET_SECTION_TYPE_FLAGS
1624 #define TARGET_SECTION_TYPE_FLAGS msp430_section_type_flags
1627 msp430_section_type_flags (tree decl
, const char * name
, int reloc
)
1629 if (strncmp (name
, lower_prefix
, strlen (lower_prefix
)) == 0)
1630 name
+= strlen (lower_prefix
);
1631 else if (strncmp (name
, upper_prefix
, strlen (upper_prefix
)) == 0)
1632 name
+= strlen (upper_prefix
);
1633 else if (strncmp (name
, either_prefix
, strlen (either_prefix
)) == 0)
1634 name
+= strlen (either_prefix
);
1636 return default_section_type_flags (decl
, name
, reloc
);
1639 #undef TARGET_ASM_UNIQUE_SECTION
1640 #define TARGET_ASM_UNIQUE_SECTION msp430_unique_section
1643 msp430_unique_section (tree decl
, int reloc
)
1645 gcc_assert (decl
!= NULL_TREE
);
1647 /* In large mode we must make sure that interrupt handlers are put into
1648 low memory as the vector table only accepts 16-bit addresses. */
1649 if (TARGET_LARGE
&& TREE_CODE (decl
) == FUNCTION_DECL
&& is_interrupt_func (decl
))
1651 set_decl_section_name (decl
, ".lowtext");
1655 default_unique_section (decl
, reloc
);
1657 const char * prefix
;
1659 if ( TREE_CODE (decl
) == STRING_CST
1660 || TREE_CODE (decl
) == CONSTRUCTOR
1661 || TREE_CODE (decl
) == INTEGER_CST
1662 || TREE_CODE (decl
) == VECTOR_CST
1663 || TREE_CODE (decl
) == COMPLEX_CST
1664 || (prefix
= gen_prefix (decl
)) == NULL
1668 const char * dec_name
= DECL_SECTION_NAME (decl
);
1669 char * name
= ACONCAT ((prefix
, dec_name
, NULL
));
1671 set_decl_section_name (decl
, name
);
1674 /* Emit a declaration of a common symbol.
1675 If a data region is in use then put the symbol into the
1676 equivalent .bss section instead. */
1679 msp430_output_aligned_decl_common (FILE * stream
,
1682 unsigned HOST_WIDE_INT size
,
1685 if (msp430_data_region
== ANY
)
1687 fprintf (stream
, COMMON_ASM_OP
);
1688 assemble_name (stream
, name
);
1689 fprintf (stream
, "," HOST_WIDE_INT_PRINT_UNSIGNED
",%u\n",
1690 size
, align
/ BITS_PER_UNIT
);
1697 sec
= msp430_select_section (decl
, 0, align
);
1699 switch (msp430_data_region
)
1701 case UPPER
: sec
= get_named_section (NULL
, ".upper.bss", 0); break;
1702 case LOWER
: sec
= get_named_section (NULL
, ".lower.bss", 0); break;
1703 case EITHER
: sec
= get_named_section (NULL
, ".either.bss", 0); break;
1707 gcc_assert (sec
!= NULL
);
1709 switch_to_section (sec
);
1710 ASM_OUTPUT_ALIGN (stream
, floor_log2 (align
/ BITS_PER_UNIT
));
1711 targetm
.asm_out
.globalize_label (stream
, name
);
1712 ASM_WEAKEN_LABEL (stream
, name
);
1713 ASM_OUTPUT_LABEL (stream
, name
);
1714 ASM_OUTPUT_SKIP (stream
, size
? size
: 1);
1719 msp430_do_not_relax_short_jumps (void)
1721 /* When placing code into "either" low or high memory we do not want the linker
1722 to grow the size of sections, which it can do if it is encounters a branch to
1723 a label that is too far away. So we tell the cbranch patterns to avoid using
1724 short jumps when there is a chance that the instructions will end up in a low
1727 msp430_code_region
== EITHER
1728 || msp430_code_region
== LOWER
1729 || has_attr (ATTR_EITHER
, current_function_decl
)
1730 || has_attr (ATTR_LOWER
, current_function_decl
);
1735 MSP430_BUILTIN_BIC_SR
,
1736 MSP430_BUILTIN_BIS_SR
,
1737 MSP430_BUILTIN_DELAY_CYCLES
,
1741 static GTY(()) tree msp430_builtins
[(int) MSP430_BUILTIN_max
];
1744 msp430_init_builtins (void)
1746 tree void_ftype_int
= build_function_type_list (void_type_node
, integer_type_node
, NULL
);
1747 tree void_ftype_longlong
= build_function_type_list (void_type_node
, long_long_integer_type_node
, NULL
);
1749 msp430_builtins
[MSP430_BUILTIN_BIC_SR
] =
1750 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int
,
1751 MSP430_BUILTIN_BIC_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
1753 msp430_builtins
[MSP430_BUILTIN_BIS_SR
] =
1754 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int
,
1755 MSP430_BUILTIN_BIS_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
1757 msp430_builtins
[MSP430_BUILTIN_DELAY_CYCLES
] =
1758 add_builtin_function ( "__delay_cycles", void_ftype_longlong
,
1759 MSP430_BUILTIN_DELAY_CYCLES
, BUILT_IN_MD
, NULL
, NULL_TREE
);
1763 msp430_builtin_decl (unsigned code
, bool initialize ATTRIBUTE_UNUSED
)
1767 case MSP430_BUILTIN_BIC_SR
:
1768 case MSP430_BUILTIN_BIS_SR
:
1769 case MSP430_BUILTIN_DELAY_CYCLES
:
1770 return msp430_builtins
[code
];
1772 return error_mark_node
;
1776 /* These constants are really register reads, which are faster than
1777 regular constants. */
1779 cg_magic_constant (HOST_WIDE_INT c
)
1797 msp430_expand_delay_cycles (rtx arg
)
1799 HOST_WIDE_INT i
, c
, n
;
1800 /* extra cycles for MSP430X instructions */
1801 #define CYCX(M,X) (msp430x ? (X) : (M))
1803 if (GET_CODE (arg
) != CONST_INT
)
1805 error ("__delay_cycles() only takes constant arguments");
1811 if (HOST_BITS_PER_WIDE_INT
> 32)
1815 error ("__delay_cycles only takes non-negative cycle counts.");
1820 emit_insn (gen_delay_cycles_start (arg
));
1822 /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
1823 if (c
> 3 * 0xffff + CYCX (7, 10))
1826 /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
1827 if (c
>= 0x10000 * 7 + CYCX (14, 16))
1830 c
-= CYCX (14, 16) + 7 * 0x10000;
1833 if ((unsigned long long) i
> 0xffffffffULL
)
1835 error ("__delay_cycles is limited to 32-bit loop counts.");
1841 i
= (c
- CYCX (14, 16)) / 7;
1842 c
-= CYCX (14, 16) + i
* 7;
1845 if (cg_magic_constant (i
& 0xffff))
1847 if (cg_magic_constant ((i
>> 16) & 0xffff))
1851 emit_insn (gen_delay_cycles_32x (GEN_INT (i
), GEN_INT (n
- c
)));
1853 emit_insn (gen_delay_cycles_32 (GEN_INT (i
), GEN_INT (n
- c
)));
1856 /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
1860 i
= (c
- CYCX (7, 10)) / 3;
1861 c
-= CYCX (7, 10) + i
* 3;
1863 if (cg_magic_constant (i
))
1867 emit_insn (gen_delay_cycles_16x (GEN_INT (i
), GEN_INT (n
- c
)));
1869 emit_insn (gen_delay_cycles_16 (GEN_INT (i
), GEN_INT (n
- c
)));
1874 emit_insn (gen_delay_cycles_2 ());
1880 emit_insn (gen_delay_cycles_1 ());
1884 emit_insn (gen_delay_cycles_end (arg
));
1890 msp430_expand_builtin (tree exp
,
1891 rtx target ATTRIBUTE_UNUSED
,
1892 rtx subtarget ATTRIBUTE_UNUSED
,
1893 machine_mode mode ATTRIBUTE_UNUSED
,
1894 int ignore ATTRIBUTE_UNUSED
)
1896 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
1897 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
1898 rtx arg1
= expand_normal (CALL_EXPR_ARG (exp
, 0));
1900 if (fcode
== MSP430_BUILTIN_DELAY_CYCLES
)
1901 return msp430_expand_delay_cycles (arg1
);
1903 if (! msp430_is_interrupt_func ())
1905 error ("MSP430 builtin functions only work inside interrupt handlers");
1909 if (! REG_P (arg1
) && ! CONSTANT_P (arg1
))
1910 arg1
= force_reg (mode
, arg1
);
1914 case MSP430_BUILTIN_BIC_SR
: emit_insn (gen_bic_SR (arg1
)); break;
1915 case MSP430_BUILTIN_BIS_SR
: emit_insn (gen_bis_SR (arg1
)); break;
1917 internal_error ("bad builtin code");
1923 #undef TARGET_INIT_BUILTINS
1924 #define TARGET_INIT_BUILTINS msp430_init_builtins
1926 #undef TARGET_EXPAND_BUILTIN
1927 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
1929 #undef TARGET_BUILTIN_DECL
1930 #define TARGET_BUILTIN_DECL msp430_builtin_decl
1933 msp430_expand_prologue (void)
1937 /* Always use stack_pointer_rtx instead of calling
1938 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
1939 that there is a single rtx representing the stack pointer,
1940 namely stack_pointer_rtx, and uses == to recognize it. */
1941 rtx sp
= stack_pointer_rtx
;
1944 if (is_naked_func ())
1946 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
1947 examines the output of the gen_prologue() function. */
1948 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
1952 emit_insn (gen_prologue_start_marker ());
1954 if (is_critical_func ())
1956 emit_insn (gen_push_intr_state ());
1957 emit_insn (gen_disable_interrupts ());
1959 else if (is_reentrant_func ())
1960 emit_insn (gen_disable_interrupts ());
1962 if (!cfun
->machine
->computed
)
1963 msp430_compute_frame_info ();
1965 if (flag_stack_usage_info
)
1966 current_function_static_stack_size
= cfun
->machine
->framesize
;
1968 if (crtl
->args
.pretend_args_size
)
1972 gcc_assert (crtl
->args
.pretend_args_size
== 2);
1974 p
= emit_insn (gen_grow_and_swap ());
1976 /* Document the stack decrement... */
1977 note
= F (gen_rtx_SET (stack_pointer_rtx
,
1978 gen_rtx_MINUS (Pmode
, stack_pointer_rtx
, GEN_INT (2))));
1979 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
1981 /* ...and the establishment of a new location for the return address. */
1982 note
= F (gen_rtx_SET (gen_rtx_MEM (Pmode
,
1983 gen_rtx_PLUS (Pmode
,
1987 add_reg_note (p
, REG_CFA_OFFSET
, note
);
1991 for (i
= 15; i
>= 4; i
--)
1992 if (cfun
->machine
->need_to_save
[i
])
1997 for (seq
= i
- 1; seq
>= 4 && cfun
->machine
->need_to_save
[seq
]; seq
--)
2003 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
2004 p
= F (emit_insn (gen_pushm (gen_rtx_REG (Pmode
, i
),
2007 note
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (count
+ 1));
2009 XVECEXP (note
, 0, 0)
2010 = F (gen_rtx_SET (stack_pointer_rtx
,
2011 gen_rtx_PLUS (Pmode
,
2013 GEN_INT (count
* (TARGET_LARGE
? -4 : -2)))));
2015 /* *sp-- = R[i-j] */
2019 for (j
= 0; j
< count
; j
++)
2022 int ofs
= (count
- j
- 1) * (TARGET_LARGE
? 4 : 2);
2025 addr
= gen_rtx_PLUS (Pmode
, sp
, GEN_INT (ofs
));
2027 addr
= stack_pointer_rtx
;
2029 XVECEXP (note
, 0, j
+ 1) =
2030 F (gen_rtx_SET (gen_rtx_MEM (Pmode
, addr
),
2031 gen_rtx_REG (Pmode
, i
- j
)) );
2034 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
2038 F (emit_insn (gen_push (gen_rtx_REG (Pmode
, i
))));
2041 if (frame_pointer_needed
)
2042 F (emit_move_insn (gen_rtx_REG (Pmode
, FRAME_POINTER_REGNUM
), sp
));
2044 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
2046 increment_stack (- fs
);
2048 emit_insn (gen_prologue_end_marker ());
2052 msp430_expand_epilogue (int is_eh
)
2058 if (is_naked_func ())
2060 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2061 examines the output of the gen_epilogue() function. */
2062 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
2066 if (cfun
->machine
->need_to_save
[10])
2068 /* Check for a helper function. */
2069 helper_n
= 7; /* For when the loop below never sees a match. */
2070 for (i
= 9; i
>= 4; i
--)
2071 if (!cfun
->machine
->need_to_save
[i
])
2075 if (cfun
->machine
->need_to_save
[i
])
2084 emit_insn (gen_epilogue_start_marker ());
2086 if (cfun
->decl
&& strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun
->decl
)), "main") == 0)
2087 emit_insn (gen_msp430_refsym_need_exit ());
2089 if (is_wakeup_func ())
2090 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
2091 status register current residing on the stack. When this function
2092 executes its RETI instruction the SR will be updated with this saved
2093 value, thus ensuring that the processor is woken up from any low power
2094 state in which it may be residing. */
2095 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
2097 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
2099 increment_stack (fs
);
2103 /* We need to add the right "SP" register save just after the
2104 regular ones, so that when we pop it off we're in the EH
2105 return frame, not this one. This overwrites our own return
2106 address, but we're not going to be returning anyway. */
2107 rtx r12
= gen_rtx_REG (Pmode
, 12);
2108 rtx (*addPmode
)(rtx
, rtx
, rtx
) = TARGET_LARGE
? gen_addpsi3
: gen_addhi3
;
2110 /* R12 will hold the new SP. */
2111 i
= cfun
->machine
->framesize_regs
;
2112 emit_move_insn (r12
, stack_pointer_rtx
);
2113 emit_insn (addPmode (r12
, r12
, EH_RETURN_STACKADJ_RTX
));
2114 emit_insn (addPmode (r12
, r12
, GEN_INT (i
)));
2115 emit_move_insn (gen_rtx_MEM (Pmode
, plus_constant (Pmode
, stack_pointer_rtx
, i
)), r12
);
2118 for (i
= 4; i
<= 15; i
++)
2119 if (cfun
->machine
->need_to_save
[i
])
2123 for (seq
= i
+ 1; seq
<= 15 && cfun
->machine
->need_to_save
[seq
]; seq
++)
2129 /* Note: With TARGET_LARGE we still use
2130 POPM as POPX.A is two bytes bigger. */
2131 emit_insn (gen_popm (stack_pointer_rtx
, GEN_INT (seq
- 1),
2135 else if (i
== 11 - helper_n
2136 && ! msp430_is_interrupt_func ()
2137 && ! is_reentrant_func ()
2138 && ! is_critical_func ()
2139 && crtl
->args
.pretend_args_size
== 0
2140 /* Calling the helper takes as many bytes as the POP;RET sequence. */
2144 emit_insn (gen_epilogue_helper (GEN_INT (helper_n
)));
2148 emit_insn (gen_pop (gen_rtx_REG (Pmode
, i
)));
2153 /* Also pop SP, which puts us into the EH return frame. Except
2154 that you can't "pop" sp, you have to just load it off the
2156 emit_move_insn (stack_pointer_rtx
, gen_rtx_MEM (Pmode
, stack_pointer_rtx
));
2159 if (crtl
->args
.pretend_args_size
)
2160 emit_insn (gen_swap_and_shrink ());
2162 if (is_critical_func ())
2163 emit_insn (gen_pop_intr_state ());
2164 else if (is_reentrant_func ())
2165 emit_insn (gen_enable_interrupts ());
2167 emit_jump_insn (gen_msp_return ());
2170 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
2171 m32c_emit_eh_epilogue. */
2173 msp430_eh_return_stackadj_rtx (void)
2175 if (!cfun
->machine
->eh_stack_adjust
)
2179 sa
= gen_rtx_REG (Pmode
, 15);
2180 cfun
->machine
->eh_stack_adjust
= sa
;
2182 return cfun
->machine
->eh_stack_adjust
;
2185 /* This function is called before reload, to "fix" the stack in
2186 preparation for an EH return. */
2188 msp430_expand_eh_return (rtx eh_handler
)
2190 /* These are all Pmode */
2191 rtx ap
, sa
, ra
, tmp
;
2193 ap
= arg_pointer_rtx
;
2194 sa
= msp430_eh_return_stackadj_rtx ();
2198 tmp
= gen_rtx_PLUS (Pmode
, ap
, sa
);
2199 tmp
= plus_constant (Pmode
, tmp
, TARGET_LARGE
? -4 : -2);
2200 tmp
= gen_rtx_MEM (Pmode
, tmp
);
2201 emit_move_insn (tmp
, ra
);
2204 #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
2205 #define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
2207 msp430_init_dwarf_reg_sizes_extra (tree address
)
2210 rtx addr
= expand_normal (address
);
2211 rtx mem
= gen_rtx_MEM (BLKmode
, addr
);
2216 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
2218 unsigned int dnum
= DWARF_FRAME_REGNUM (i
);
2219 unsigned int rnum
= DWARF2_FRAME_REG_OUT (dnum
, 1);
2221 if (rnum
< DWARF_FRAME_REGISTERS
)
2223 HOST_WIDE_INT offset
= rnum
* GET_MODE_SIZE (QImode
);
2225 emit_move_insn (adjust_address (mem
, QImode
, offset
),
2226 gen_int_mode (4, QImode
));
2231 /* This is a list of MD patterns that implement fixed-count shifts. */
2237 rtx (*genfunc
)(rtx
,rtx
);
2239 const_shift_helpers
[] =
2241 #define CSH(N,C,X,G) { "__mspabi_" N, C, X, gen_##G }
2243 CSH ("slli", 1, 1, slli_1
),
2244 CSH ("slll", 1, 1, slll_1
),
2245 CSH ("slll", 2, 1, slll_2
),
2247 CSH ("srai", 1, 0, srai_1
),
2248 CSH ("sral", 1, 0, sral_1
),
2249 CSH ("sral", 2, 0, sral_2
),
2251 CSH ("srll", 1, 0, srll_1
),
2252 CSH ("srll", 2, 1, srll_2x
),
2257 /* The MSP430 ABI defines a number of helper functions that should be
2258 used for, for example, 32-bit shifts. This function is called to
2259 emit such a function, using the table above to optimize some
2262 msp430_expand_helper (rtx
*operands
, const char *helper_name
, bool const_variants
)
2265 char *helper_const
= NULL
;
2268 machine_mode arg0mode
= GET_MODE (operands
[0]);
2269 machine_mode arg1mode
= GET_MODE (operands
[1]);
2270 machine_mode arg2mode
= GET_MODE (operands
[2]);
2271 int have_430x
= msp430x
? 1 : 0;
2273 if (CONST_INT_P (operands
[2]))
2277 for (i
=0; const_shift_helpers
[i
].name
; i
++)
2279 if (const_shift_helpers
[i
].need_430x
<= have_430x
2280 && strcmp (helper_name
, const_shift_helpers
[i
].name
) == 0
2281 && INTVAL (operands
[2]) == const_shift_helpers
[i
].count
)
2283 emit_insn (const_shift_helpers
[i
].genfunc (operands
[0], operands
[1]));
2289 if (arg1mode
== VOIDmode
)
2290 arg1mode
= arg0mode
;
2291 if (arg2mode
== VOIDmode
)
2292 arg2mode
= arg0mode
;
2294 if (arg1mode
== SImode
)
2301 && CONST_INT_P (operands
[2])
2302 && INTVAL (operands
[2]) >= 1
2303 && INTVAL (operands
[2]) <= 15)
2305 /* Note that the INTVAL is limited in value and length by the conditional above. */
2306 int len
= strlen (helper_name
) + 4;
2307 helper_const
= (char *) xmalloc (len
);
2308 snprintf (helper_const
, len
, "%s_%d", helper_name
, (int) INTVAL (operands
[2]));
2311 emit_move_insn (gen_rtx_REG (arg1mode
, 12),
2314 emit_move_insn (gen_rtx_REG (arg2mode
, arg2
),
2317 c
= gen_call_value_internal (gen_rtx_REG (arg0mode
, 12),
2318 gen_rtx_SYMBOL_REF (VOIDmode
, helper_const
? helper_const
: helper_name
),
2320 c
= emit_call_insn (c
);
2321 RTL_CONST_CALL_P (c
) = 1;
2324 use_regs (&f
, 12, arg1sz
);
2326 use_regs (&f
, arg2
, 1);
2327 add_function_usage_to (c
, f
);
2329 emit_move_insn (operands
[0],
2330 gen_rtx_REG (arg0mode
, 12));
2333 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
2335 msp430_fixup_compare_operands (machine_mode my_mode
, rtx
* operands
)
2337 /* constants we're looking for, not constants which are allowed. */
2338 int const_op_idx
= 1;
2340 if (msp430_reversible_cmp_operator (operands
[0], VOIDmode
))
2343 if (GET_CODE (operands
[const_op_idx
]) != REG
2344 && GET_CODE (operands
[const_op_idx
]) != MEM
)
2345 operands
[const_op_idx
] = copy_to_mode_reg (my_mode
, operands
[const_op_idx
]);
2348 /* Simplify_gen_subreg() doesn't handle memory references the way we
2349 need it to below, so we use this function for when we must get a
2350 valid subreg in a "natural" state. */
2352 msp430_subreg (machine_mode mode
, rtx r
, machine_mode omode
, int byte
)
2356 if (GET_CODE (r
) == SUBREG
2357 && SUBREG_BYTE (r
) == 0)
2359 rtx ireg
= SUBREG_REG (r
);
2360 machine_mode imode
= GET_MODE (ireg
);
2362 /* special case for (HI (SI (PSI ...), 0)) */
2363 if (imode
== PSImode
2366 rv
= gen_rtx_SUBREG (mode
, ireg
, byte
);
2368 rv
= simplify_gen_subreg (mode
, ireg
, imode
, byte
);
2370 else if (GET_CODE (r
) == MEM
)
2371 rv
= adjust_address (r
, mode
, byte
);
2372 else if (GET_CODE (r
) == SYMBOL_REF
2373 && (byte
== 0 || byte
== 2)
2376 rv
= gen_rtx_ZERO_EXTRACT (HImode
, r
, GEN_INT (16), GEN_INT (8*byte
));
2377 rv
= gen_rtx_CONST (HImode
, r
);
2380 rv
= simplify_gen_subreg (mode
, r
, omode
, byte
);
2388 /* Called by movsi_x to generate the HImode operands. */
2390 msp430_split_movsi (rtx
*operands
)
2392 rtx op00
, op02
, op10
, op12
;
2394 op00
= msp430_subreg (HImode
, operands
[0], SImode
, 0);
2395 op02
= msp430_subreg (HImode
, operands
[0], SImode
, 2);
2397 if (GET_CODE (operands
[1]) == CONST
2398 || GET_CODE (operands
[1]) == SYMBOL_REF
)
2400 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
2401 op10
= gen_rtx_CONST (HImode
, op10
);
2402 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
2403 op12
= gen_rtx_CONST (HImode
, op12
);
2407 op10
= msp430_subreg (HImode
, operands
[1], SImode
, 0);
2408 op12
= msp430_subreg (HImode
, operands
[1], SImode
, 2);
2411 if (rtx_equal_p (operands
[0], operands
[1]))
2418 else if (rtx_equal_p (op00
, op12
)
2419 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
2420 || (REG_P (op00
) && reg_mentioned_p (op00
, op10
))
2421 /* Or storing (rN) into mem (rN). */
2422 || (REG_P (op10
) && reg_mentioned_p (op10
, op00
))
2440 /* The MSPABI specifies the names of various helper functions, many of
2441 which are compatible with GCC's helpers. This table maps the GCC
2442 name to the MSPABI name. */
2445 char const * const gcc_name
;
2446 char const * const ti_name
;
2448 helper_function_name_mappings
[] =
2450 /* Floating point to/from integer conversions. */
2451 { "__truncdfsf2", "__mspabi_cvtdf" },
2452 { "__extendsfdf2", "__mspabi_cvtfd" },
2453 { "__fixdfhi", "__mspabi_fixdi" },
2454 { "__fixdfsi", "__mspabi_fixdli" },
2455 { "__fixdfdi", "__mspabi_fixdlli" },
2456 { "__fixunsdfhi", "__mspabi_fixdu" },
2457 { "__fixunsdfsi", "__mspabi_fixdul" },
2458 { "__fixunsdfdi", "__mspabi_fixdull" },
2459 { "__fixsfhi", "__mspabi_fixfi" },
2460 { "__fixsfsi", "__mspabi_fixfli" },
2461 { "__fixsfdi", "__mspabi_fixflli" },
2462 { "__fixunsfhi", "__mspabi_fixfu" },
2463 { "__fixunsfsi", "__mspabi_fixful" },
2464 { "__fixunsfdi", "__mspabi_fixfull" },
2465 { "__floathisf", "__mspabi_fltif" },
2466 { "__floatsisf", "__mspabi_fltlif" },
2467 { "__floatdisf", "__mspabi_fltllif" },
2468 { "__floathidf", "__mspabi_fltid" },
2469 { "__floatsidf", "__mspabi_fltlid" },
2470 { "__floatdidf", "__mspabi_fltllid" },
2471 { "__floatunhisf", "__mspabi_fltuf" },
2472 { "__floatunsisf", "__mspabi_fltulf" },
2473 { "__floatundisf", "__mspabi_fltullf" },
2474 { "__floatunhidf", "__mspabi_fltud" },
2475 { "__floatunsidf", "__mspabi_fltuld" },
2476 { "__floatundidf", "__mspabi_fltulld" },
2478 /* Floating point comparisons. */
2479 /* GCC uses individual functions for each comparison, TI uses one
2480 compare <=> function. */
2482 /* Floating point arithmatic */
2483 { "__adddf3", "__mspabi_addd" },
2484 { "__addsf3", "__mspabi_addf" },
2485 { "__divdf3", "__mspabi_divd" },
2486 { "__divsf3", "__mspabi_divf" },
2487 { "__muldf3", "__mspabi_mpyd" },
2488 { "__mulsf3", "__mspabi_mpyf" },
2489 { "__subdf3", "__mspabi_subd" },
2490 { "__subsf3", "__mspabi_subf" },
2491 /* GCC does not use helper functions for negation */
2493 /* Integer multiply, divide, remainder. */
2494 { "__mulhi3", "__mspabi_mpyi" },
2495 { "__mulsi3", "__mspabi_mpyl" },
2496 { "__muldi3", "__mspabi_mpyll" },
2498 /* Clarify signed vs unsigned first. */
2499 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
2500 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
2503 { "__divhi3", "__mspabi_divi" },
2504 { "__divsi3", "__mspabi_divli" },
2505 { "__divdi3", "__mspabi_divlli" },
2506 { "__udivhi3", "__mspabi_divu" },
2507 { "__udivsi3", "__mspabi_divlu" },
2508 { "__udivdi3", "__mspabi_divllu" },
2509 { "__modhi3", "__mspabi_remi" },
2510 { "__modsi3", "__mspabi_remli" },
2511 { "__moddi3", "__mspabi_remlli" },
2512 { "__umodhi3", "__mspabi_remu" },
2513 { "__umodsi3", "__mspabi_remul" },
2514 { "__umoddi3", "__mspabi_remull" },
2516 /* Bitwise operations. */
2517 /* Rotation - no rotation support yet. */
2518 /* Logical left shift - gcc already does these itself. */
2519 /* Arithmetic left shift - gcc already does these itself. */
2520 /* Arithmetic right shift - gcc already does these itself. */
2525 /* Returns true if the current MCU supports an F5xxx series
2526 hardware multiper. */
2529 msp430_use_f5_series_hwmult (void)
2531 static const char * cached_match
= NULL
;
2532 static bool cached_result
;
2534 if (msp430_hwmult_type
== F5SERIES
)
2537 if (target_mcu
== NULL
|| msp430_hwmult_type
!= AUTO
)
2540 if (target_mcu
== cached_match
)
2541 return cached_result
;
2543 cached_match
= target_mcu
;
2545 if (strncasecmp (target_mcu
, "msp430f5", 8) == 0)
2546 return cached_result
= true;
2547 if (strncasecmp (target_mcu
, "msp430fr5", 9) == 0)
2548 return cached_result
= true;
2549 if (strncasecmp (target_mcu
, "msp430f6", 8) == 0)
2550 return cached_result
= true;
2552 static const char * known_f5_mult_mcus
[] =
2554 "cc430f5123", "cc430f5125", "cc430f5133",
2555 "cc430f5135", "cc430f5137", "cc430f5143",
2556 "cc430f5145", "cc430f5147", "cc430f6125",
2557 "cc430f6126", "cc430f6127", "cc430f6135",
2558 "cc430f6137", "cc430f6143", "cc430f6145",
2559 "cc430f6147", "msp430bt5190", "msp430sl5438a",
2564 for (i
= ARRAY_SIZE (known_f5_mult_mcus
); i
--;)
2565 if (strcasecmp (target_mcu
, known_f5_mult_mcus
[i
]) == 0)
2566 return cached_result
= true;
2568 return cached_result
= false;
2571 /* Returns true if the current MCU has a second generation
2572 32-bit hardware multiplier. */
2575 use_32bit_hwmult (void)
2577 static const char * known_32bit_mult_mcus
[] =
2579 "msp430f4783", "msp430f4793", "msp430f4784",
2580 "msp430f4794", "msp430f47126", "msp430f47127",
2581 "msp430f47163", "msp430f47173", "msp430f47183",
2582 "msp430f47193", "msp430f47166", "msp430f47176",
2583 "msp430f47186", "msp430f47196", "msp430f47167",
2584 "msp430f47177", "msp430f47187", "msp430f47197"
2586 static const char * cached_match
= NULL
;
2587 static bool cached_result
;
2590 if (msp430_hwmult_type
== LARGE
)
2593 if (target_mcu
== NULL
|| msp430_hwmult_type
!= AUTO
)
2596 if (target_mcu
== cached_match
)
2597 return cached_result
;
2599 cached_match
= target_mcu
;
2600 for (i
= ARRAY_SIZE (known_32bit_mult_mcus
); i
--;)
2601 if (strcasecmp (target_mcu
, known_32bit_mult_mcus
[i
]) == 0)
2602 return cached_result
= true;
2604 return cached_result
= false;
2607 /* Returns true if the current MCU does not have a
2608 hardware multiplier of any kind. */
2611 msp430_no_hwmult (void)
2613 static const char * known_nomult_mcus
[] =
2615 "msp430c091", "msp430c092", "msp430c111",
2616 "msp430c1111", "msp430c112", "msp430c1121",
2617 "msp430c1331", "msp430c1351", "msp430c311s",
2618 "msp430c312", "msp430c313", "msp430c314",
2619 "msp430c315", "msp430c323", "msp430c325",
2620 "msp430c412", "msp430c413", "msp430e112",
2621 "msp430e313", "msp430e315", "msp430e325",
2622 "msp430f110", "msp430f1101", "msp430f1101a",
2623 "msp430f1111", "msp430f1111a", "msp430f112",
2624 "msp430f1121", "msp430f1121a", "msp430f1122",
2625 "msp430f1132", "msp430f122", "msp430f1222",
2626 "msp430f123", "msp430f1232", "msp430f133",
2627 "msp430f135", "msp430f155", "msp430f156",
2628 "msp430f157", "msp430f2001", "msp430f2002",
2629 "msp430f2003", "msp430f2011", "msp430f2012",
2630 "msp430f2013", "msp430f2101", "msp430f2111",
2631 "msp430f2112", "msp430f2121", "msp430f2122",
2632 "msp430f2131", "msp430f2132", "msp430f2232",
2633 "msp430f2234", "msp430f2252", "msp430f2254",
2634 "msp430f2272", "msp430f2274", "msp430f412",
2635 "msp430f413", "msp430f4132", "msp430f415",
2636 "msp430f4152", "msp430f417", "msp430f4250",
2637 "msp430f4260", "msp430f4270", "msp430f435",
2638 "msp430f4351", "msp430f436", "msp430f4361",
2639 "msp430f437", "msp430f4371", "msp430f438",
2640 "msp430f439", "msp430f477", "msp430f478",
2641 "msp430f479", "msp430fe423", "msp430fe4232",
2642 "msp430fe423a", "msp430fe4242", "msp430fe425",
2643 "msp430fe4252", "msp430fe425a", "msp430fe427",
2644 "msp430fe4272", "msp430fe427a", "msp430fg4250",
2645 "msp430fg4260", "msp430fg4270", "msp430fg437",
2646 "msp430fg438", "msp430fg439", "msp430fg477",
2647 "msp430fg478", "msp430fg479", "msp430fr2032",
2648 "msp430fr2033", "msp430fr4131", "msp430fr4132",
2649 "msp430fr4133", "msp430fw423", "msp430fw425",
2650 "msp430fw427", "msp430fw428", "msp430fw429",
2651 "msp430g2001", "msp430g2101", "msp430g2102",
2652 "msp430g2111", "msp430g2112", "msp430g2113",
2653 "msp430g2121", "msp430g2131", "msp430g2132",
2654 "msp430g2152", "msp430g2153", "msp430g2201",
2655 "msp430g2202", "msp430g2203", "msp430g2210",
2656 "msp430g2211", "msp430g2212", "msp430g2213",
2657 "msp430g2221", "msp430g2230", "msp430g2231",
2658 "msp430g2232", "msp430g2233", "msp430g2252",
2659 "msp430g2253", "msp430g2302", "msp430g2303",
2660 "msp430g2312", "msp430g2313", "msp430g2332",
2661 "msp430g2333", "msp430g2352", "msp430g2353",
2662 "msp430g2402", "msp430g2403", "msp430g2412",
2663 "msp430g2413", "msp430g2432", "msp430g2433",
2664 "msp430g2444", "msp430g2452", "msp430g2453",
2665 "msp430g2513", "msp430g2533", "msp430g2544",
2666 "msp430g2553", "msp430g2744", "msp430g2755",
2667 "msp430g2855", "msp430g2955", "msp430l092",
2668 "msp430p112", "msp430p313", "msp430p315",
2669 "msp430p315s", "msp430p325", "msp430tch5e"
2671 static const char * cached_match
= NULL
;
2672 static bool cached_result
;
2675 if (msp430_hwmult_type
== NONE
)
2678 if (target_mcu
== NULL
|| msp430_hwmult_type
!= AUTO
)
2681 if (target_mcu
== cached_match
)
2682 return cached_result
;
2684 cached_match
= target_mcu
;
2685 for (i
= ARRAY_SIZE (known_nomult_mcus
); i
--;)
2686 if (strcasecmp (target_mcu
, known_nomult_mcus
[i
]) == 0)
2687 return cached_result
= true;
2689 return cached_result
= false;
2692 /* This function does the same as the default, but it will replace GCC
2693 function names with the MSPABI-specified ones. */
2696 msp430_output_labelref (FILE *file
, const char *name
)
2700 for (i
= 0; helper_function_name_mappings
[i
].gcc_name
; i
++)
2701 if (strcmp (helper_function_name_mappings
[i
].gcc_name
, name
) == 0)
2703 name
= helper_function_name_mappings
[i
].ti_name
;
2707 /* If we have been given a specific MCU name then we may be
2708 able to make use of its hardware multiply capabilities. */
2709 if (msp430_hwmult_type
!= NONE
)
2711 if (strcmp ("__mspabi_mpyi", name
) == 0)
2713 if (msp430_use_f5_series_hwmult ())
2714 name
= "__mulhi2_f5";
2715 else if (! msp430_no_hwmult ())
2718 else if (strcmp ("__mspabi_mpyl", name
) == 0)
2720 if (msp430_use_f5_series_hwmult ())
2721 name
= "__mulsi2_f5";
2722 else if (use_32bit_hwmult ())
2723 name
= "__mulsi2_hw32";
2724 else if (! msp430_no_hwmult ())
2732 /* Common code for msp430_print_operand... */
2735 msp430_print_operand_raw (FILE * file
, rtx op
)
2739 switch (GET_CODE (op
))
2742 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
2748 fprintf (file
, "%#" HOST_WIDE_INT_PRINT
"x", i
);
2750 fprintf (file
, "%" HOST_WIDE_INT_PRINT
"d", i
);
2758 output_addr_const (file
, op
);
2762 print_rtl (file
, op
);
2767 #undef TARGET_PRINT_OPERAND_ADDRESS
2768 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
2770 /* Output to stdio stream FILE the assembler syntax for an
2771 instruction operand that is a memory reference whose address
2775 msp430_print_operand_addr (FILE * file
, rtx addr
)
2777 switch (GET_CODE (addr
))
2780 msp430_print_operand_raw (file
, XEXP (addr
, 1));
2781 gcc_assert (REG_P (XEXP (addr
, 0)));
2782 fprintf (file
, "(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
2786 fprintf (file
, "@");
2793 fprintf (file
, "&");
2800 msp430_print_operand_raw (file
, addr
);
2803 #undef TARGET_PRINT_OPERAND
2804 #define TARGET_PRINT_OPERAND msp430_print_operand
2806 /* A low 16-bits of int/lower of register pair
2807 B high 16-bits of int/higher of register pair
2808 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
2809 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
2810 H like %B (for backwards compatibility)
2812 J an integer without a # prefix
2813 L like %A (for backwards compatibility)
2814 O offset of the top of the stack
2815 Q like X but generates an A postfix
2816 R inverse of condition code, unsigned.
2817 X X instruction postfix in large mode
2820 b .B or .W or .A, depending upon the mode
2822 r inverse of condition code
2823 x like X but only for pointers. */
2826 msp430_print_operand (FILE * file
, rtx op
, int letter
)
2830 /* We can't use c, n, a, or l. */
2834 gcc_assert (CONST_INT_P (op
));
2835 /* Print the constant value, less one. */
2836 fprintf (file
, "#%ld", INTVAL (op
) - 1);
2839 gcc_assert (CONST_INT_P (op
));
2840 /* Print the constant value, less four. */
2841 fprintf (file
, "#%ld", INTVAL (op
) - 4);
2844 if (GET_CODE (op
) == CONST_INT
)
2846 /* Inverse of constants */
2847 int i
= INTVAL (op
);
2848 fprintf (file
, "%d", ~i
);
2853 case 'r': /* Conditional jump where the condition is reversed. */
2854 switch (GET_CODE (op
))
2856 case EQ
: fprintf (file
, "NE"); break;
2857 case NE
: fprintf (file
, "EQ"); break;
2858 case GEU
: fprintf (file
, "LO"); break;
2859 case LTU
: fprintf (file
, "HS"); break;
2860 case GE
: fprintf (file
, "L"); break;
2861 case LT
: fprintf (file
, "GE"); break;
2862 /* Assume these have reversed operands. */
2863 case GTU
: fprintf (file
, "HS"); break;
2864 case LEU
: fprintf (file
, "LO"); break;
2865 case GT
: fprintf (file
, "GE"); break;
2866 case LE
: fprintf (file
, "L"); break;
2868 msp430_print_operand_raw (file
, op
);
2872 case 'R': /* Conditional jump where the operands are reversed. */
2873 switch (GET_CODE (op
))
2875 case GTU
: fprintf (file
, "LO"); break;
2876 case LEU
: fprintf (file
, "HS"); break;
2877 case GT
: fprintf (file
, "L"); break;
2878 case LE
: fprintf (file
, "GE"); break;
2880 msp430_print_operand_raw (file
, op
);
2884 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
2885 gcc_assert (CONST_INT_P (op
));
2886 fprintf (file
, "#%d", 1 << INTVAL (op
));
2889 switch (GET_MODE (op
))
2891 case QImode
: fprintf (file
, ".B"); return;
2892 case HImode
: fprintf (file
, ".W"); return;
2893 case PSImode
: fprintf (file
, ".A"); return;
2894 case SImode
: fprintf (file
, ".A"); return;
2899 case 'L': /* Low half. */
2900 switch (GET_CODE (op
))
2903 op
= adjust_address (op
, Pmode
, 0);
2908 op
= GEN_INT (INTVAL (op
) & 0xffff);
2912 /* If you get here, figure out a test case :-) */
2917 case 'H': /* high half */
2918 switch (GET_CODE (op
))
2921 op
= adjust_address (op
, Pmode
, 2);
2924 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 1);
2927 op
= GEN_INT (INTVAL (op
) >> 16);
2931 /* If you get here, figure out a test case :-) */
2936 switch (GET_CODE (op
))
2939 op
= adjust_address (op
, Pmode
, 3);
2942 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 2);
2945 op
= GEN_INT ((long long) INTVAL (op
) >> 32);
2949 /* If you get here, figure out a test case :-) */
2954 switch (GET_CODE (op
))
2957 op
= adjust_address (op
, Pmode
, 4);
2960 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 3);
2963 op
= GEN_INT ((long long) INTVAL (op
) >> 48);
2967 /* If you get here, figure out a test case :-) */
2973 /* This is used to turn, for example, an ADD opcode into an ADDX
2974 opcode when we're using 20-bit addresses. */
2975 if (TARGET_LARGE
|| GET_MODE (op
) == PSImode
)
2976 fprintf (file
, "X");
2977 /* We don't care which operand we use, but we want 'X' in the MD
2978 file, so we do it this way. */
2982 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
2983 if (GET_MODE (op
) == PSImode
)
2984 fprintf (file
, "X");
2988 /* Likewise, for BR -> BRA. */
2990 fprintf (file
, "A");
2994 /* Computes the offset to the top of the stack for the current frame.
2995 This has to be done here rather than in, say, msp430_expand_builtin()
2996 because builtins are expanded before the frame layout is determined. */
2997 fprintf (file
, "%d",
2998 msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, STACK_POINTER_REGNUM
)
2999 - (TARGET_LARGE
? 4 : 2));
3003 gcc_assert (GET_CODE (op
) == CONST_INT
);
3007 output_operand_lossage ("invalid operand prefix");
3011 switch (GET_CODE (op
))
3014 msp430_print_operand_raw (file
, op
);
3018 addr
= XEXP (op
, 0);
3019 msp430_print_operand_addr (file
, addr
);
3023 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTRACT
)
3026 switch (INTVAL (XEXP (op
, 2)))
3029 fprintf (file
, "#lo (");
3030 msp430_print_operand_raw (file
, XEXP (op
, 0));
3031 fprintf (file
, ")");
3035 fprintf (file
, "#hi (");
3036 msp430_print_operand_raw (file
, XEXP (op
, 0));
3037 fprintf (file
, ")");
3041 output_operand_lossage ("invalid zero extract");
3051 fprintf (file
, "#");
3052 msp430_print_operand_raw (file
, op
);
3055 case EQ
: fprintf (file
, "EQ"); break;
3056 case NE
: fprintf (file
, "NE"); break;
3057 case GEU
: fprintf (file
, "HS"); break;
3058 case LTU
: fprintf (file
, "LO"); break;
3059 case GE
: fprintf (file
, "GE"); break;
3060 case LT
: fprintf (file
, "L"); break;
3063 print_rtl (file
, op
);
3072 msp430_return_addr_rtx (int count
)
3078 ra_size
= TARGET_LARGE
? 4 : 2;
3079 if (crtl
->args
.pretend_args_size
)
3082 return gen_rtx_MEM (Pmode
, gen_rtx_PLUS (Pmode
, arg_pointer_rtx
, GEN_INT (- ra_size
)));
3086 msp430_incoming_return_addr_rtx (void)
3088 return gen_rtx_MEM (Pmode
, stack_pointer_rtx
);
3091 /* Instruction generation stuff. */
3093 /* Generate a sequence of instructions to sign-extend an HI
3094 value into an SI value. Handles the tricky case where
3095 we are overwriting the destination. */
3098 msp430x_extendhisi (rtx
* operands
)
3100 if (REGNO (operands
[0]) == REGNO (operands
[1]))
3101 /* Low word of dest == source word. */
3102 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
3105 /* Note: This sequence is approximately the same length as invoking a helper
3106 function to perform the sign-extension, as in:
3110 CALL __mspabi_srai_15
3113 but this version does not involve any function calls or using argument
3114 registers, so it reduces register pressure. */
3115 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
3117 if (REGNO (operands
[0]) + 1 == REGNO (operands
[1]))
3118 /* High word of dest == source word. */
3119 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
3121 /* No overlap between dest and source. */
3122 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
3125 /* Likewise for logical right shifts. */
3127 msp430x_logical_shift_right (rtx amount
)
3129 /* The MSP430X's logical right shift instruction - RRUM - does
3130 not use an extension word, so we cannot encode a repeat count.
3131 Try various alternatives to work around this. If the count
3132 is in a register we are stuck, hence the assert. */
3133 gcc_assert (CONST_INT_P (amount
));
3135 if (INTVAL (amount
) <= 0
3136 || INTVAL (amount
) >= 16)
3137 return "# nop logical shift.";
3139 if (INTVAL (amount
) > 0
3140 && INTVAL (amount
) < 5)
3141 return "rrum.w\t%2, %0"; /* Two bytes. */
3143 if (INTVAL (amount
) > 4
3144 && INTVAL (amount
) < 9)
3145 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
3147 /* First we logically shift right by one. Now we know
3148 that the top bit is zero and we can use the arithmetic
3149 right shift instruction to perform the rest of the shift. */
3150 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
3153 struct gcc_target targetm
= TARGET_INITIALIZER
;
3155 #include "gt-msp430.h"