1 /* Subroutines used for code generation on TI MSP430 processors.
2 Copyright (C) 2012-2014 Free Software Foundation, Inc.
3 Contributed by Red Hat.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
26 #include "stor-layout.h"
30 #include "hard-reg-set.h"
31 #include "insn-config.h"
32 #include "conditions.h"
34 #include "insn-attr.h"
41 #include "diagnostic-core.h"
49 #include "target-def.h"
50 #include "langhooks.h"
51 #include "msp430-protos.h"
57 static void msp430_compute_frame_info (void);
61 /* Run-time Target Specification */
65 struct GTY(()) machine_function
67 /* If set, the rest of the fields have been computed. */
69 /* Which registers need to be saved in the pro/epilogue. */
70 int need_to_save
[FIRST_PSEUDO_REGISTER
];
72 /* These fields describe the frame layout... */
74 /* 2/4 bytes for saved PC */
78 int framesize_outgoing
;
82 /* How much we adjust the stack when returning from an exception
87 /* This is our init_machine_status, as set in
88 msp_option_override. */
89 static struct machine_function
*
90 msp430_init_machine_status (void)
92 struct machine_function
*m
;
94 m
= ggc_alloc_cleared_machine_function ();
99 #undef TARGET_HANDLE_OPTION
100 #define TARGET_HANDLE_OPTION msp430_handle_option
103 msp430_handle_option (struct gcc_options
*opts ATTRIBUTE_UNUSED
,
104 struct gcc_options
*opts_set ATTRIBUTE_UNUSED
,
105 const struct cl_decoded_option
*decoded ATTRIBUTE_UNUSED
,
106 location_t loc ATTRIBUTE_UNUSED
)
111 #undef TARGET_OPTION_OVERRIDE
112 #define TARGET_OPTION_OVERRIDE msp430_option_override
114 /* This list provides a set of known MCU names that support the MSP430X
115 ISA. The list has been provided by TI and should be kept in sync with
118 gcc/config/msp430/t-msp430
119 gas/config/tc-msp430.c
121 FIXME: We ought to read the names in from a file at run, rather
122 than having them built in like this. Also such a file should be
125 static const char * msp430x_names
[] =
127 "cc430f5123", "cc430f5125", "cc430f5133", "cc430f5135", "cc430f5137",
128 "cc430f5143", "cc430f5145", "cc430f5147", "cc430f6125", "cc430f6126",
129 "cc430f6127", "cc430f6135", "cc430f6137", "cc430f6143", "cc430f6145",
130 "cc430f6147", "msp430bt5190", "msp430cg4616", "msp430cg4617", "msp430cg4618",
131 "msp430cg4619", "msp430f2416", "msp430f2417", "msp430f2418", "msp430f2419",
132 "msp430f2616", "msp430f2617", "msp430f2618", "msp430f2619", "msp430f4616",
133 "msp430f46161", "msp430f4617", "msp430f46171", "msp430f4618", "msp430f46181",
134 "msp430f4619", "msp430f46191", "msp430f47126", "msp430f47127", "msp430f47163",
135 "msp430f47166", "msp430f47167", "msp430f47173", "msp430f47176", "msp430f47177",
136 "msp430f47183", "msp430f47186", "msp430f47187", "msp430f47193", "msp430f47196",
137 "msp430f47197", "msp430f5131", "msp430f5132", "msp430f5151", "msp430f5152",
138 "msp430f5171", "msp430f5172", "msp430f5212", "msp430f5213", "msp430f5214",
139 "msp430f5217", "msp430f5218", "msp430f5219", "msp430f5222", "msp430f5223",
140 "msp430f5224", "msp430f5227", "msp430f5228", "msp430f5229", "msp430f5304",
141 "msp430f5308", "msp430f5309", "msp430f5310", "msp430f5324", "msp430f5325",
142 "msp430f5326", "msp430f5327", "msp430f5328", "msp430f5329", "msp430f5333",
143 "msp430f5335", "msp430f5336", "msp430f5338", "msp430f5340", "msp430f5341",
144 "msp430f5342", "msp430f5358", "msp430f5359", "msp430f5418", "msp430f5418a",
145 "msp430f5419", "msp430f5419a", "msp430f5435", "msp430f5435a", "msp430f5436",
146 "msp430f5436a", "msp430f5437", "msp430f5437a", "msp430f5438", "msp430f5438a",
147 "msp430f5500", "msp430f5501", "msp430f5502", "msp430f5503", "msp430f5504",
148 "msp430f5505", "msp430f5506", "msp430f5507", "msp430f5508", "msp430f5509",
149 "msp430f5510", "msp430f5513", "msp430f5514", "msp430f5515", "msp430f5517",
150 "msp430f5519", "msp430f5521", "msp430f5522", "msp430f5524", "msp430f5525",
151 "msp430f5526", "msp430f5527", "msp430f5528", "msp430f5529", "msp430f5630",
152 "msp430f5631", "msp430f5632", "msp430f5633", "msp430f5634", "msp430f5635",
153 "msp430f5636", "msp430f5637", "msp430f5638", "msp430f5658", "msp430f5659",
154 "msp430f6433", "msp430f6435", "msp430f6436", "msp430f6438", "msp430f6458",
155 "msp430f6459", "msp430f6630", "msp430f6631", "msp430f6632", "msp430f6633",
156 "msp430f6634", "msp430f6635", "msp430f6636", "msp430f6637", "msp430f6638",
157 "msp430f6658", "msp430f6659", "msp430f6720", "msp430f6721", "msp430f6723",
158 "msp430f6724", "msp430f6725", "msp430f6726", "msp430f6730", "msp430f6731",
159 "msp430f6733", "msp430f6734", "msp430f6735", "msp430f6736", "msp430f6745",
160 "msp430f67451", "msp430f6746", "msp430f67461", "msp430f6747", "msp430f67471",
161 "msp430f6748", "msp430f67481", "msp430f6749", "msp430f67491", "msp430f6765",
162 "msp430f67651", "msp430f6766", "msp430f67661", "msp430f6767", "msp430f67671",
163 "msp430f6768", "msp430f67681", "msp430f6769", "msp430f67691", "msp430f6775",
164 "msp430f67751", "msp430f6776", "msp430f67761", "msp430f6777", "msp430f67771",
165 "msp430f6778", "msp430f67781", "msp430f6779", "msp430f67791", "msp430fg4616",
166 "msp430fg4617", "msp430fg4618", "msp430fg4619", "msp430fr5720", "msp430fr5721",
167 "msp430fr5722", "msp430fr5723", "msp430fr5724", "msp430fr5725", "msp430fr5726",
168 "msp430fr5727", "msp430fr5728", "msp430fr5729", "msp430fr5730", "msp430fr5731",
169 "msp430fr5732", "msp430fr5733", "msp430fr5734", "msp430fr5735", "msp430fr5736",
170 "msp430fr5737", "msp430fr5738", "msp430fr5739", "msp430fr5949", "msp430fr5969",
171 "msp430sl5438a","msp430x241x", "msp430x26x", "msp430x461x1", "msp430x46x",
172 "msp430x471x3", "msp430x471x6", "msp430x471x7", "msp430xg46x"
175 /* Generate a C preprocessor symbol based upon the MCU selected by the user.
176 If a specific MCU has not been selected then return a generic symbol instead. */
179 msp430_mcu_name (void)
184 static char mcu_name
[64];
186 snprintf (mcu_name
, sizeof (mcu_name
) - 1, "__%s__", target_mcu
);
187 for (i
= strlen (mcu_name
); i
--;)
188 mcu_name
[i
] = TOUPPER (mcu_name
[i
]);
192 return msp430x
? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
196 msp430_option_override (void)
198 init_machine_status
= msp430_init_machine_status
;
202 if (strcasecmp (target_cpu
, "msp430x") == 0
203 || strcasecmp (target_cpu
, "msp430xv2") == 0)
211 for (i
= ARRAY_SIZE (msp430x_names
); i
--;)
212 if (strcasecmp (target_mcu
, msp430x_names
[i
]) == 0)
217 /* Note - it is not an error if we did not recognize the MCU
218 name. The msp430x_names array only contains those MCU names
219 which are currently known to use the MSP430X ISA. There are
220 lots of other MCUs which just use the MSP430 ISA. */
222 /* We also recognise two generic MCU 430X names. They do not
223 appear in the msp430x_names table as we want to be able to
224 generate special C preprocessor defines for them. That is
225 why we set target_mcu to NULL. */
226 if (strcasecmp (target_mcu
, "msp430x") == 0
227 || strcasecmp (target_mcu
, "msp430xv2") == 0)
234 if (TARGET_LARGE
&& !msp430x
)
235 error ("-mlarge requires a 430X-compatible -mmcu=");
237 if (flag_exceptions
|| flag_non_call_exceptions
238 || flag_unwind_tables
|| flag_asynchronous_unwind_tables
)
239 flag_omit_frame_pointer
= false;
241 flag_omit_frame_pointer
= true;
243 /* This is a hack to work around a problem with the newlib build
244 mechanism. Newlib always appends CFLAGS to the end of the GCC
245 command line and always sets -O2 in CFLAGS. Thus it is not
246 possible to build newlib with -Os enabled. Until now... */
247 if (TARGET_OPT_SPACE
&& optimize
< 3)
255 #undef TARGET_MS_BITFIELD_LAYOUT_P
256 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
259 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED
)
268 /* Implements HARD_REGNO_NREGS. MSP430X registers can hold a single
269 PSImode value, but not an SImode value. */
271 msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED
,
272 enum machine_mode mode
)
274 if (mode
== PSImode
&& msp430x
)
276 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
280 /* Implements HARD_REGNO_MODE_OK. */
282 msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED
,
283 enum machine_mode mode
)
285 return regno
<= (ARG_POINTER_REGNUM
- msp430_hard_regno_nregs (regno
, mode
));
288 /* Implements MODES_TIEABLE_P. */
290 msp430_modes_tieable_p (enum machine_mode mode1
, enum machine_mode mode2
)
292 if ((mode1
== PSImode
|| mode2
== SImode
)
293 || (mode1
== SImode
|| mode2
== PSImode
))
296 return ((GET_MODE_CLASS (mode1
) == MODE_FLOAT
297 || GET_MODE_CLASS (mode1
) == MODE_COMPLEX_FLOAT
)
298 == (GET_MODE_CLASS (mode2
) == MODE_FLOAT
299 || GET_MODE_CLASS (mode2
) == MODE_COMPLEX_FLOAT
));
302 #undef TARGET_FRAME_POINTER_REQUIRED
303 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
306 msp430_frame_pointer_required (void)
311 #undef TARGET_CAN_ELIMINATE
312 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
315 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED
,
316 const int to_reg ATTRIBUTE_UNUSED
)
321 /* Implements INITIAL_ELIMINATION_OFFSET. */
323 msp430_initial_elimination_offset (int from
, int to
)
325 int rv
= 0; /* As if arg to arg. */
327 msp430_compute_frame_info ();
331 case STACK_POINTER_REGNUM
:
332 rv
+= cfun
->machine
->framesize_outgoing
;
333 rv
+= cfun
->machine
->framesize_locals
;
335 case FRAME_POINTER_REGNUM
:
336 rv
+= cfun
->machine
->framesize_regs
;
337 /* Allow for the saved return address. */
338 rv
+= (TARGET_LARGE
? 4 : 2);
339 /* NB/ No need to allow for crtl->args.pretend_args_size.
340 GCC does that for us. */
348 case FRAME_POINTER_REGNUM
:
349 /* Allow for the fall through above. */
350 rv
-= (TARGET_LARGE
? 4 : 2);
351 rv
-= cfun
->machine
->framesize_regs
;
352 case ARG_POINTER_REGNUM
:
361 /* Named Address Space support */
364 /* Return the appropriate mode for a named address pointer. */
365 #undef TARGET_ADDR_SPACE_POINTER_MODE
366 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
367 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
368 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
370 static enum machine_mode
371 msp430_addr_space_pointer_mode (addr_space_t addrspace
)
376 case ADDR_SPACE_GENERIC
:
378 case ADDR_SPACE_NEAR
:
385 /* Function pointers are stored in unwind_word sized
386 variables, so make sure that unwind_word is big enough. */
387 #undef TARGET_UNWIND_WORD_MODE
388 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
390 static enum machine_mode
391 msp430_unwind_word_mode (void)
393 return TARGET_LARGE
? SImode
: HImode
;
396 /* Determine if one named address space is a subset of another. */
397 #undef TARGET_ADDR_SPACE_SUBSET_P
398 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
400 msp430_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
402 if (subset
== superset
)
405 return (subset
!= ADDR_SPACE_FAR
&& superset
== ADDR_SPACE_FAR
);
408 #undef TARGET_ADDR_SPACE_CONVERT
409 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
410 /* Convert from one address space to another. */
412 msp430_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
414 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
415 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
418 if (to_as
!= ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_FAR
)
420 /* This is unpredictable, as we're truncating off usable address
424 return gen_rtx_CONST (HImode
, op
);
426 result
= gen_reg_rtx (HImode
);
427 emit_insn (gen_truncpsihi2 (result
, op
));
430 else if (to_as
== ADDR_SPACE_FAR
&& from_as
!= ADDR_SPACE_FAR
)
432 /* This always works. */
435 return gen_rtx_CONST (PSImode
, op
);
437 result
= gen_reg_rtx (PSImode
);
438 emit_insn (gen_zero_extendhipsi2 (result
, op
));
445 /* Stack Layout and Calling Conventions. */
447 /* For each function, we list the gcc version and the TI version on
448 each line, where we're converting the function names. */
449 static char const * const special_convention_function_names
[] =
451 "__muldi3", "__mspabi_mpyll",
452 "__udivdi3", "__mspabi_divull",
453 "__umoddi3", "__mspabi_remull",
454 "__divdi3", "__mspabi_divlli",
455 "__moddi3", "__mspabi_remlli",
459 "__adddf3", "__mspabi_addd",
460 "__subdf3", "__mspabi_subd",
461 "__muldf3", "__mspabi_mpyd",
462 "__divdf3", "__mspabi_divd",
467 /* TRUE if the function passed is a "speical" function. Special
468 functions pass two DImode parameters in registers. */
470 msp430_special_register_convention_p (const char *name
)
474 for (i
= 0; special_convention_function_names
[i
]; i
++)
475 if (! strcmp (name
, special_convention_function_names
[i
]))
481 #undef TARGET_FUNCTION_VALUE_REGNO_P
482 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
485 msp430_function_value_regno_p (unsigned int regno
)
491 #undef TARGET_FUNCTION_VALUE
492 #define TARGET_FUNCTION_VALUE msp430_function_value
495 msp430_function_value (const_tree ret_type
,
496 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
497 bool outgoing ATTRIBUTE_UNUSED
)
499 return gen_rtx_REG (TYPE_MODE (ret_type
), 12);
502 #undef TARGET_LIBCALL_VALUE
503 #define TARGET_LIBCALL_VALUE msp430_libcall_value
506 msp430_libcall_value (enum machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
508 return gen_rtx_REG (mode
, 12);
511 /* Implements INIT_CUMULATIVE_ARGS. */
513 msp430_init_cumulative_args (CUMULATIVE_ARGS
*ca
,
514 tree fntype ATTRIBUTE_UNUSED
,
515 rtx libname ATTRIBUTE_UNUSED
,
516 tree fndecl ATTRIBUTE_UNUSED
,
517 int n_named_args ATTRIBUTE_UNUSED
)
520 memset (ca
, 0, sizeof(*ca
));
525 fname
= IDENTIFIER_POINTER (DECL_NAME (fndecl
));
527 fname
= XSTR (libname
, 0);
531 if (fname
&& msp430_special_register_convention_p (fname
))
535 /* Helper function for argument passing; this function is the common
536 code that determines where an argument will be passed. */
538 msp430_evaluate_arg (cumulative_args_t cap
,
539 enum machine_mode mode
,
540 const_tree type ATTRIBUTE_UNUSED
,
543 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
544 int nregs
= GET_MODE_SIZE (mode
);
556 nregs
= (nregs
+ 1) / 2;
560 /* Function is passed two DImode operands, in R8:R11 and
570 for (i
= 0; i
< 4; i
++)
571 if (! ca
->reg_used
[i
])
574 ca
->start_reg
= CA_FIRST_REG
+ i
;
579 for (i
= 0; i
< 3; i
++)
580 if (! ca
->reg_used
[i
] && ! ca
->reg_used
[i
+ 1])
583 ca
->start_reg
= CA_FIRST_REG
+ i
;
586 if (! ca
->reg_used
[3] && ca
->can_split
)
590 ca
->start_reg
= CA_FIRST_REG
+ 3;
597 if (! ca
->reg_used
[0]
598 && ! ca
->reg_used
[1]
599 && ! ca
->reg_used
[2]
600 && ! ca
->reg_used
[3])
603 ca
->start_reg
= CA_FIRST_REG
;
610 #undef TARGET_PROMOTE_PROTOTYPES
611 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
614 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED
)
619 #undef TARGET_FUNCTION_ARG
620 #define TARGET_FUNCTION_ARG msp430_function_arg
623 msp430_function_arg (cumulative_args_t cap
,
624 enum machine_mode mode
,
628 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
630 msp430_evaluate_arg (cap
, mode
, type
, named
);
633 return gen_rtx_REG (mode
, ca
->start_reg
);
638 #undef TARGET_ARG_PARTIAL_BYTES
639 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
642 msp430_arg_partial_bytes (cumulative_args_t cap
,
643 enum machine_mode mode
,
647 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
649 msp430_evaluate_arg (cap
, mode
, type
, named
);
651 if (ca
->reg_count
&& ca
->mem_count
)
652 return ca
->reg_count
* UNITS_PER_WORD
;
657 #undef TARGET_PASS_BY_REFERENCE
658 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
661 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED
,
662 enum machine_mode mode
,
664 bool named ATTRIBUTE_UNUSED
)
666 return (mode
== BLKmode
667 || (type
&& TREE_CODE (type
) == RECORD_TYPE
)
668 || (type
&& TREE_CODE (type
) == UNION_TYPE
));
671 #undef TARGET_CALLEE_COPIES
672 #define TARGET_CALLEE_COPIES msp430_callee_copies
675 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED
,
676 enum machine_mode mode ATTRIBUTE_UNUSED
,
677 const_tree type ATTRIBUTE_UNUSED
,
678 bool named ATTRIBUTE_UNUSED
)
683 #undef TARGET_FUNCTION_ARG_ADVANCE
684 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
687 msp430_function_arg_advance (cumulative_args_t cap
,
688 enum machine_mode mode
,
692 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
695 msp430_evaluate_arg (cap
, mode
, type
, named
);
697 if (ca
->start_reg
>= CA_FIRST_REG
)
698 for (i
= 0; i
< ca
->reg_count
; i
++)
699 ca
->reg_used
[i
+ ca
->start_reg
- CA_FIRST_REG
] = 1;
704 #undef TARGET_FUNCTION_ARG_BOUNDARY
705 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
708 msp430_function_arg_boundary (enum machine_mode mode
, const_tree type
)
711 && int_size_in_bytes (type
) > 1)
713 if (GET_MODE_BITSIZE (mode
) > 8)
718 #undef TARGET_RETURN_IN_MEMORY
719 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
722 msp430_return_in_memory (const_tree ret_type
, const_tree fntype ATTRIBUTE_UNUSED
)
724 enum machine_mode mode
= TYPE_MODE (ret_type
);
727 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == RECORD_TYPE
)
728 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == UNION_TYPE
))
731 if (GET_MODE_SIZE (mode
) > 8)
737 #undef TARGET_GET_RAW_ARG_MODE
738 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
740 static enum machine_mode
741 msp430_get_raw_arg_mode (int regno
)
743 return (regno
== ARG_POINTER_REGNUM
) ? VOIDmode
: Pmode
;
746 #undef TARGET_GET_RAW_RESULT_MODE
747 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
749 static enum machine_mode
750 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED
)
755 /* Addressing Modes */
757 #undef TARGET_LEGITIMATE_ADDRESS_P
758 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
761 reg_ok_for_addr (rtx r
, bool strict
)
765 if (strict
&& rn
>= FIRST_PSEUDO_REGISTER
)
766 rn
= reg_renumber
[rn
];
767 if (strict
&& 0 <= rn
&& rn
< FIRST_PSEUDO_REGISTER
)
775 msp430_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED
,
776 rtx x ATTRIBUTE_UNUSED
,
777 bool strict ATTRIBUTE_UNUSED
)
779 switch (GET_CODE (x
))
785 if (REG_P (XEXP (x
, 0)))
787 if (GET_MODE (x
) != GET_MODE (XEXP (x
, 0)))
789 if (!reg_ok_for_addr (XEXP (x
, 0), strict
))
791 switch (GET_CODE (XEXP (x
, 1)))
804 if (!reg_ok_for_addr (x
, strict
))
817 #undef TARGET_LEGITIMATE_CONSTANT_P
818 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
821 msp430_legitimate_constant (enum machine_mode mode
, rtx x
)
823 return ! CONST_INT_P (x
)
825 /* GCC does not know the width of the PSImode, so make
826 sure that it does not try to use a constant value that
828 || (INTVAL (x
) < (1 << 20) && INTVAL (x
) >= (-1 << 20));
832 #undef TARGET_RTX_COSTS
833 #define TARGET_RTX_COSTS msp430_rtx_costs
835 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED
,
837 int outer_code ATTRIBUTE_UNUSED
,
838 int opno ATTRIBUTE_UNUSED
,
840 bool speed ATTRIBUTE_UNUSED
)
845 if (GET_MODE (x
) == SImode
&& outer_code
== SET
)
847 *total
= COSTS_N_INSNS (4);
856 *total
= COSTS_N_INSNS (100);
864 /* Function Entry and Exit */
866 /* The MSP430 call frame looks like this:
869 +--------------------+
873 +--------------------+ <-- "arg pointer"
875 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
877 +--------------------+
878 | SR if this func has|
879 | been called via an |
881 +--------------------+ <-- SP before prologue, also AP
883 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
885 +--------------------+ <-- "frame pointer"
889 +--------------------+
893 +--------------------+ <-- SP during function
898 /* We use this to wrap all emitted insns in the prologue, so they get
899 the "frame-related" (/f) flag set. */
903 RTX_FRAME_RELATED_P (x
) = 1;
907 /* This is the one spot that decides if a register is to be saved and
908 restored in the prologue/epilogue. */
910 msp430_preserve_reg_p (int regno
)
912 /* PC, SP, SR, and the constant generator. */
916 /* FIXME: add interrupt, EH, etc. */
917 if (crtl
->calls_eh_return
)
920 /* Shouldn't be more than the above, but just in case... */
921 if (fixed_regs
[regno
])
924 /* Interrupt handlers save all registers they use, even
925 ones which are call saved. If they call other functions
926 then *every* register is saved. */
927 if (msp430_is_interrupt_func ())
928 return ! crtl
->is_leaf
|| df_regs_ever_live_p (regno
);
930 if (!call_used_regs
[regno
]
931 && df_regs_ever_live_p (regno
))
937 /* Compute all the frame-related fields in our machine_function
940 msp430_compute_frame_info (void)
944 cfun
->machine
->computed
= 1;
945 cfun
->machine
->framesize_regs
= 0;
946 cfun
->machine
->framesize_locals
= get_frame_size ();
947 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
949 for (i
= 0; i
< ARG_POINTER_REGNUM
; i
++)
950 if (msp430_preserve_reg_p (i
))
952 cfun
->machine
->need_to_save
[i
] = 1;
953 cfun
->machine
->framesize_regs
+= (TARGET_LARGE
? 4 : 2);
956 cfun
->machine
->need_to_save
[i
] = 0;
958 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
959 cfun
->machine
->framesize_locals
++;
961 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
962 + cfun
->machine
->framesize_locals
963 + cfun
->machine
->framesize_outgoing
);
967 is_attr_func (const char * attr
)
969 return lookup_attribute (attr
, DECL_ATTRIBUTES (current_function_decl
)) != NULL_TREE
;
972 /* Returns true if the current function has the "interrupt" attribute. */
975 msp430_is_interrupt_func (void)
977 return is_attr_func ("interrupt");
981 is_wakeup_func (void)
983 return msp430_is_interrupt_func () && is_attr_func ("wakeup");
989 return is_attr_func ("naked");
993 is_reentrant_func (void)
995 return is_attr_func ("reentrant");
999 is_critical_func (void)
1001 return is_attr_func ("critical");
1004 #undef TARGET_ASM_FUNCTION_PROLOGUE
1005 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
1008 msp430_start_function (FILE *outfile
, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED
)
1012 fprintf (outfile
, "; start of function\n");
1014 if (DECL_ATTRIBUTES (current_function_decl
) != NULL_TREE
)
1016 fprintf (outfile
, "; attributes: ");
1017 if (is_naked_func ())
1018 fprintf (outfile
, "naked ");
1019 if (msp430_is_interrupt_func ())
1020 fprintf (outfile
, "interrupt ");
1021 if (is_reentrant_func ())
1022 fprintf (outfile
, "reentrant ");
1023 if (is_critical_func ())
1024 fprintf (outfile
, "critical ");
1025 if (is_wakeup_func ())
1026 fprintf (outfile
, "wakeup ");
1027 fprintf (outfile
, "\n");
1030 fprintf (outfile
, "; framesize_regs: %d\n", cfun
->machine
->framesize_regs
);
1031 fprintf (outfile
, "; framesize_locals: %d\n", cfun
->machine
->framesize_locals
);
1032 fprintf (outfile
, "; framesize_outgoing: %d\n", cfun
->machine
->framesize_outgoing
);
1033 fprintf (outfile
, "; framesize: %d\n", cfun
->machine
->framesize
);
1034 fprintf (outfile
, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, FRAME_POINTER_REGNUM
));
1035 fprintf (outfile
, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM
, STACK_POINTER_REGNUM
));
1038 fprintf (outfile
, "; saved regs:");
1039 for (r
= 0; r
< ARG_POINTER_REGNUM
; r
++)
1040 if (cfun
->machine
->need_to_save
[r
])
1042 fprintf (outfile
, " %s", reg_names
[r
]);
1046 fprintf (outfile
, "(none)");
1047 fprintf (outfile
, "\n");
1050 /* Common code to change the stack pointer. */
1052 increment_stack (HOST_WIDE_INT amount
)
1055 rtx sp
= stack_pointer_rtx
;
1062 inc
= GEN_INT (- amount
);
1064 F (emit_insn (gen_subpsi3 (sp
, sp
, inc
)));
1066 F (emit_insn (gen_subhi3 (sp
, sp
, inc
)));
1070 inc
= GEN_INT (amount
);
1072 emit_insn (gen_addpsi3 (sp
, sp
, inc
));
1074 emit_insn (gen_addhi3 (sp
, sp
, inc
));
1078 /* Verify MSP430 specific attributes. */
1081 msp430_attr (tree
* node
,
1084 int flags ATTRIBUTE_UNUSED
,
1085 bool * no_add_attrs
)
1087 gcc_assert (DECL_P (* node
));
1091 tree value
= TREE_VALUE (args
);
1093 switch (TREE_CODE (value
))
1096 if ( strcmp (TREE_STRING_POINTER (value
), "reset")
1097 && strcmp (TREE_STRING_POINTER (value
), "nmi")
1098 && strcmp (TREE_STRING_POINTER (value
), "watchdog"))
1099 /* Allow the attribute to be added - the linker script
1100 being used may still recognise this name. */
1101 warning (OPT_Wattributes
,
1102 "unrecognised interrupt vector argument of %qE attribute",
1107 if (TREE_INT_CST_LOW (value
) > 63)
1108 /* Allow the attribute to be added - the linker script
1109 being used may still recognise this value. */
1110 warning (OPT_Wattributes
,
1111 "numeric argument of %qE attribute must be in range 0..63",
1116 warning (OPT_Wattributes
,
1117 "argument of %qE attribute is not a string constant or number",
1119 *no_add_attrs
= true;
1124 if (TREE_CODE (* node
) != FUNCTION_DECL
)
1126 warning (OPT_Wattributes
,
1127 "%qE attribute only applies to functions",
1129 * no_add_attrs
= true;
1132 /* FIXME: We ought to check that the interrupt handler
1133 attribute has been applied to a void function. */
1134 /* FIXME: We should check that reentrant and critical
1135 functions are not naked and that critical functions
1136 are not reentrant. */
1141 #undef TARGET_ATTRIBUTE_TABLE
1142 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
1144 /* Table of MSP430-specific attributes. */
1145 const struct attribute_spec msp430_attribute_table
[] =
1147 /* Name min_len decl_req, fn_type_req, affects_type_identity
1148 max_len, type_req, handler. */
1149 { "interrupt", 0, 1, true, false, false, msp430_attr
, false },
1150 { "naked", 0, 0, true, false, false, msp430_attr
, false },
1151 { "reentrant", 0, 0, true, false, false, msp430_attr
, false },
1152 { "critical", 0, 0, true, false, false, msp430_attr
, false },
1153 { "wakeup", 0, 0, true, false, false, msp430_attr
, false },
1154 { NULL
, 0, 0, false, false, false, NULL
, false }
1158 msp430_start_function (FILE *file
, const char *name
, tree decl
)
1162 int_attr
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl
));
1163 if (int_attr
!= NULL_TREE
)
1165 tree intr_vector
= TREE_VALUE (int_attr
);
1167 if (intr_vector
!= NULL_TREE
)
1171 intr_vector
= TREE_VALUE (intr_vector
);
1173 /* The interrupt attribute has a vector value. Turn this into a
1174 section name, switch to that section and put the address of
1175 the current function into that vector slot. Note msp430_attr()
1176 has already verified the vector name for us. */
1177 if (TREE_CODE (intr_vector
) == STRING_CST
)
1178 sprintf (buf
, "__interrupt_vector_%.80s",
1179 TREE_STRING_POINTER (intr_vector
));
1180 else /* TREE_CODE (intr_vector) == INTEGER_CST */
1181 sprintf (buf
, "__interrupt_vector_%u",
1182 (unsigned int) TREE_INT_CST_LOW (intr_vector
));
1184 switch_to_section (get_section (buf
, SECTION_CODE
, decl
));
1185 fputs ("\t.word\t", file
);
1186 assemble_name (file
, name
);
1192 switch_to_section (function_section (decl
));
1193 ASM_OUTPUT_FUNCTION_LABEL (file
, name
, decl
);
1197 msp430_function_section (tree decl
, enum node_frequency freq
, bool startup
, bool exit
)
1199 /* In large mode we must make sure that interrupt handlers are put into
1200 low memory as the vector table only accepts 16-bit addresses. */
1202 && lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl
)))
1203 return get_section (".lowtext", SECTION_CODE
| SECTION_WRITE
, decl
);
1205 /* Otherwise, use the default function section. */
1206 return default_function_section (decl
, freq
, startup
, exit
);
1209 #undef TARGET_ASM_FUNCTION_SECTION
1210 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
1214 MSP430_BUILTIN_BIC_SR
,
1215 MSP430_BUILTIN_BIS_SR
,
1219 static GTY(()) tree msp430_builtins
[(int) MSP430_BUILTIN_max
];
1222 msp430_init_builtins (void)
1224 tree void_ftype_int
= build_function_type_list (void_type_node
, integer_type_node
, NULL
);
1226 msp430_builtins
[MSP430_BUILTIN_BIC_SR
] =
1227 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int
,
1228 MSP430_BUILTIN_BIC_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
1230 msp430_builtins
[MSP430_BUILTIN_BIS_SR
] =
1231 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int
,
1232 MSP430_BUILTIN_BIS_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
1236 msp430_builtin_decl (unsigned code
, bool initialize ATTRIBUTE_UNUSED
)
1240 case MSP430_BUILTIN_BIC_SR
:
1241 case MSP430_BUILTIN_BIS_SR
:
1242 return msp430_builtins
[code
];
1244 return error_mark_node
;
1249 msp430_expand_builtin (tree exp
,
1250 rtx target ATTRIBUTE_UNUSED
,
1251 rtx subtarget ATTRIBUTE_UNUSED
,
1252 enum machine_mode mode ATTRIBUTE_UNUSED
,
1253 int ignore ATTRIBUTE_UNUSED
)
1255 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
1256 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
1257 rtx arg1
= expand_normal (CALL_EXPR_ARG (exp
, 0));
1259 if (! msp430_is_interrupt_func ())
1261 error ("MSP430 builtin functions only work inside interrupt handlers");
1265 if (! REG_P (arg1
) && ! CONSTANT_P (arg1
))
1266 arg1
= force_reg (mode
, arg1
);
1270 case MSP430_BUILTIN_BIC_SR
: emit_insn (gen_bic_SR (arg1
)); break;
1271 case MSP430_BUILTIN_BIS_SR
: emit_insn (gen_bis_SR (arg1
)); break;
1273 internal_error ("bad builtin code");
1279 #undef TARGET_INIT_BUILTINS
1280 #define TARGET_INIT_BUILTINS msp430_init_builtins
1282 #undef TARGET_EXPAND_BUILTIN
1283 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
1285 #undef TARGET_BUILTIN_DECL
1286 #define TARGET_BUILTIN_DECL msp430_builtin_decl
1289 msp430_expand_prologue (void)
1293 /* Always use stack_pointer_rtx instead of calling
1294 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
1295 that there is a single rtx representing the stack pointer,
1296 namely stack_pointer_rtx, and uses == to recognize it. */
1297 rtx sp
= stack_pointer_rtx
;
1300 if (is_naked_func ())
1303 emit_insn (gen_prologue_start_marker ());
1305 if (is_critical_func ())
1307 emit_insn (gen_push_intr_state ());
1308 emit_insn (gen_disable_interrupts ());
1310 else if (is_reentrant_func ())
1311 emit_insn (gen_disable_interrupts ());
1313 if (!cfun
->machine
->computed
)
1314 msp430_compute_frame_info ();
1316 if (flag_stack_usage_info
)
1317 current_function_static_stack_size
= cfun
->machine
->framesize
;
1319 if (crtl
->args
.pretend_args_size
)
1323 gcc_assert (crtl
->args
.pretend_args_size
== 2);
1325 p
= emit_insn (gen_grow_and_swap ());
1327 /* Document the stack decrement... */
1328 note
= F (gen_rtx_SET (Pmode
, stack_pointer_rtx
,
1329 gen_rtx_MINUS (Pmode
, stack_pointer_rtx
, GEN_INT (2))));
1330 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
1332 /* ...and the establishment of a new location for the return address. */
1333 note
= F (gen_rtx_SET (Pmode
, gen_rtx_MEM (Pmode
,
1334 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, GEN_INT (-2))),
1336 add_reg_note (p
, REG_CFA_OFFSET
, note
);
1340 for (i
= 15; i
>= 4; i
--)
1341 if (cfun
->machine
->need_to_save
[i
])
1346 for (seq
= i
- 1; seq
>= 4 && cfun
->machine
->need_to_save
[seq
]; seq
--)
1352 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
1353 p
= F (emit_insn (gen_pushm (gen_rtx_REG (Pmode
, i
),
1356 note
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (count
+ 1));
1358 XVECEXP (note
, 0, 0)
1359 = F (gen_rtx_SET (VOIDmode
,
1361 gen_rtx_PLUS (Pmode
,
1363 GEN_INT (count
* (TARGET_LARGE
? -4 : -2)))));
1365 /* *sp-- = R[i-j] */
1369 for (j
= 0; j
< count
; j
++)
1372 int ofs
= (count
- j
- 1) * (TARGET_LARGE
? 4 : 2);
1375 addr
= gen_rtx_PLUS (Pmode
, sp
, GEN_INT (ofs
));
1377 addr
= stack_pointer_rtx
;
1379 XVECEXP (note
, 0, j
+ 1) =
1380 F (gen_rtx_SET (VOIDmode
,
1381 gen_rtx_MEM (Pmode
, addr
),
1382 gen_rtx_REG (Pmode
, i
- j
)) );
1385 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
1389 F (emit_insn (gen_push (gen_rtx_REG (Pmode
, i
))));
1392 if (frame_pointer_needed
)
1393 F (emit_move_insn (gen_rtx_REG (Pmode
, FRAME_POINTER_REGNUM
), sp
));
1395 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1397 increment_stack (- fs
);
1399 emit_insn (gen_prologue_end_marker ());
1403 msp430_expand_epilogue (int is_eh
)
1409 if (is_naked_func ())
1412 if (cfun
->machine
->need_to_save
[10])
1414 /* Check for a helper function. */
1415 helper_n
= 7; /* For when the loop below never sees a match. */
1416 for (i
= 9; i
>= 4; i
--)
1417 if (!cfun
->machine
->need_to_save
[i
])
1421 if (cfun
->machine
->need_to_save
[i
])
1430 emit_insn (gen_epilogue_start_marker ());
1432 if (cfun
->decl
&& strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun
->decl
)), "main") == 0)
1433 emit_insn (gen_msp430_refsym_need_exit ());
1435 if (is_wakeup_func ())
1436 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
1437 status register current residing on the stack. When this function
1438 executes its RETI instruction the SR will be updated with this saved
1439 value, thus ensuring that the processor is woken up from any low power
1440 state in which it may be residing. */
1441 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
1443 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1445 increment_stack (fs
);
1449 /* We need to add the right "SP" register save just after the
1450 regular ones, so that when we pop it off we're in the EH
1451 return frame, not this one. This overwrites our own return
1452 address, but we're not going to be returning anyway. */
1453 rtx r12
= gen_rtx_REG (Pmode
, 12);
1454 rtx (*addPmode
)(rtx
, rtx
, rtx
) = TARGET_LARGE
? gen_addpsi3
: gen_addhi3
;
1456 /* R12 will hold the new SP. */
1457 i
= cfun
->machine
->framesize_regs
;
1458 emit_move_insn (r12
, stack_pointer_rtx
);
1459 emit_insn (addPmode (r12
, r12
, EH_RETURN_STACKADJ_RTX
));
1460 emit_insn (addPmode (r12
, r12
, GEN_INT (i
)));
1461 emit_move_insn (gen_rtx_MEM (Pmode
, plus_constant (Pmode
, stack_pointer_rtx
, i
)), r12
);
1464 for (i
= 4; i
<= 15; i
++)
1465 if (cfun
->machine
->need_to_save
[i
])
1469 for (seq
= i
+ 1; seq
<= 15 && cfun
->machine
->need_to_save
[seq
]; seq
++)
1475 /* Note: With TARGET_LARGE we still use
1476 POPM as POPX.A is two bytes bigger. */
1477 emit_insn (gen_popm (stack_pointer_rtx
, GEN_INT (seq
- 1),
1481 else if (i
== 11 - helper_n
1482 && ! msp430_is_interrupt_func ()
1483 && ! is_reentrant_func ()
1484 && ! is_critical_func ()
1485 && crtl
->args
.pretend_args_size
== 0
1486 /* Calling the helper takes as many bytes as the POP;RET sequence. */
1490 emit_insn (gen_epilogue_helper (GEN_INT (helper_n
)));
1494 emit_insn (gen_pop (gen_rtx_REG (Pmode
, i
)));
1499 /* Also pop SP, which puts us into the EH return frame. Except
1500 that you can't "pop" sp, you have to just load it off the
1502 emit_move_insn (stack_pointer_rtx
, gen_rtx_MEM (Pmode
, stack_pointer_rtx
));
1505 if (crtl
->args
.pretend_args_size
)
1506 emit_insn (gen_swap_and_shrink ());
1508 if (is_critical_func ())
1509 emit_insn (gen_pop_intr_state ());
1510 else if (is_reentrant_func ())
1511 emit_insn (gen_enable_interrupts ());
1513 emit_jump_insn (gen_msp_return ());
1516 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
1517 m32c_emit_eh_epilogue. */
1519 msp430_eh_return_stackadj_rtx (void)
1521 if (!cfun
->machine
->eh_stack_adjust
)
1525 sa
= gen_rtx_REG (Pmode
, 15);
1526 cfun
->machine
->eh_stack_adjust
= sa
;
1528 return cfun
->machine
->eh_stack_adjust
;
1531 /* This function is called before reload, to "fix" the stack in
1532 preparation for an EH return. */
1534 msp430_expand_eh_return (rtx eh_handler
)
1536 /* These are all Pmode */
1537 rtx ap
, sa
, ra
, tmp
;
1539 ap
= arg_pointer_rtx
;
1540 sa
= msp430_eh_return_stackadj_rtx ();
1544 tmp
= gen_rtx_PLUS (Pmode
, ap
, sa
);
1545 tmp
= plus_constant (Pmode
, tmp
, TARGET_LARGE
? -4 : -2);
1546 tmp
= gen_rtx_MEM (Pmode
, tmp
);
1547 emit_move_insn (tmp
, ra
);
1550 /* This is a list of MD patterns that implement fixed-count shifts. */
1556 rtx (*genfunc
)(rtx
,rtx
);
1558 const_shift_helpers
[] =
1560 #define CSH(N,C,X,G) { "__mspabi_"N, C, X, gen_##G }
1562 CSH ("slli", 1, 1, slli_1
),
1563 CSH ("slll", 1, 1, slll_1
),
1564 CSH ("slll", 2, 1, slll_2
),
1566 CSH ("srai", 1, 0, srai_1
),
1567 CSH ("sral", 1, 0, sral_1
),
1568 CSH ("sral", 2, 0, sral_2
),
1570 CSH ("srll", 1, 0, srll_1
),
1571 CSH ("srll", 2, 1, srll_2x
),
1576 /* The MSP430 ABI defines a number of helper functions that should be
1577 used for, for example, 32-bit shifts. This function is called to
1578 emit such a function, using the table above to optimize some
1581 msp430_expand_helper (rtx
*operands
, const char *helper_name
, bool const_variants
)
1584 char *helper_const
= NULL
;
1587 enum machine_mode arg0mode
= GET_MODE (operands
[0]);
1588 enum machine_mode arg1mode
= GET_MODE (operands
[1]);
1589 enum machine_mode arg2mode
= GET_MODE (operands
[2]);
1590 int have_430x
= msp430x
? 1 : 0;
1592 if (CONST_INT_P (operands
[2]))
1596 for (i
=0; const_shift_helpers
[i
].name
; i
++)
1598 if (const_shift_helpers
[i
].need_430x
<= have_430x
1599 && strcmp (helper_name
, const_shift_helpers
[i
].name
) == 0
1600 && INTVAL (operands
[2]) == const_shift_helpers
[i
].count
)
1602 emit_insn (const_shift_helpers
[i
].genfunc (operands
[0], operands
[1]));
1608 if (arg1mode
== VOIDmode
)
1609 arg1mode
= arg0mode
;
1610 if (arg2mode
== VOIDmode
)
1611 arg2mode
= arg0mode
;
1613 if (arg1mode
== SImode
)
1620 && CONST_INT_P (operands
[2])
1621 && INTVAL (operands
[2]) >= 1
1622 && INTVAL (operands
[2]) <= 15)
1624 /* Note that the INTVAL is limited in value and length by the conditional above. */
1625 int len
= strlen (helper_name
) + 4;
1626 helper_const
= (char *) xmalloc (len
);
1627 snprintf (helper_const
, len
, "%s_%d", helper_name
, (int) INTVAL (operands
[2]));
1630 emit_move_insn (gen_rtx_REG (arg1mode
, 12),
1633 emit_move_insn (gen_rtx_REG (arg2mode
, arg2
),
1636 c
= gen_call_value_internal (gen_rtx_REG (arg0mode
, 12),
1637 gen_rtx_SYMBOL_REF (VOIDmode
, helper_const
? helper_const
: helper_name
),
1639 c
= emit_call_insn (c
);
1640 RTL_CONST_CALL_P (c
) = 1;
1643 use_regs (&f
, 12, arg1sz
);
1645 use_regs (&f
, arg2
, 1);
1646 add_function_usage_to (c
, f
);
1648 emit_move_insn (operands
[0],
1649 gen_rtx_REG (arg0mode
, 12));
1652 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
1654 msp430_fixup_compare_operands (enum machine_mode my_mode
, rtx
* operands
)
1656 /* constants we're looking for, not constants which are allowed. */
1657 int const_op_idx
= 1;
1659 if (msp430_reversible_cmp_operator (operands
[0], VOIDmode
))
1662 if (GET_CODE (operands
[const_op_idx
]) != REG
1663 && GET_CODE (operands
[const_op_idx
]) != MEM
)
1664 operands
[const_op_idx
] = copy_to_mode_reg (my_mode
, operands
[const_op_idx
]);
1667 /* Simplify_gen_subreg() doesn't handle memory references the way we
1668 need it to below, so we use this function for when we must get a
1669 valid subreg in a "natural" state. */
1671 msp430_subreg (enum machine_mode mode
, rtx r
, enum machine_mode omode
, int byte
)
1675 if (GET_CODE (r
) == SUBREG
1676 && SUBREG_BYTE (r
) == 0)
1678 rtx ireg
= SUBREG_REG (r
);
1679 enum machine_mode imode
= GET_MODE (ireg
);
1681 /* special case for (HI (SI (PSI ...), 0)) */
1682 if (imode
== PSImode
1685 rv
= gen_rtx_SUBREG (mode
, ireg
, byte
);
1687 rv
= simplify_gen_subreg (mode
, ireg
, imode
, byte
);
1689 else if (GET_CODE (r
) == MEM
)
1690 rv
= adjust_address (r
, mode
, byte
);
1692 rv
= simplify_gen_subreg (mode
, r
, omode
, byte
);
1700 /* Called by movsi_x to generate the HImode operands. */
1702 msp430_split_movsi (rtx
*operands
)
1704 rtx op00
, op02
, op10
, op12
;
1706 op00
= msp430_subreg (HImode
, operands
[0], SImode
, 0);
1707 op02
= msp430_subreg (HImode
, operands
[0], SImode
, 2);
1709 if (GET_CODE (operands
[1]) == CONST
1710 || GET_CODE (operands
[1]) == SYMBOL_REF
)
1712 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
1713 op10
= gen_rtx_CONST (HImode
, op10
);
1714 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
1715 op12
= gen_rtx_CONST (HImode
, op12
);
1719 op10
= msp430_subreg (HImode
, operands
[1], SImode
, 0);
1720 op12
= msp430_subreg (HImode
, operands
[1], SImode
, 2);
1723 if (rtx_equal_p (operands
[0], operands
[1]))
1730 else if (rtx_equal_p (op00
, op12
)
1731 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
1732 || (REG_P (op00
) && reg_mentioned_p (op00
, op10
))
1733 /* Or storing (rN) into mem (rN). */
1734 || (REG_P (op10
) && reg_mentioned_p (op10
, op00
))
1752 /* The MSPABI specifies the names of various helper functions, many of
1753 which are compatible with GCC's helpers. This table maps the GCC
1754 name to the MSPABI name. */
1757 char const * const gcc_name
;
1758 char const * const ti_name
;
1760 helper_function_name_mappings
[] =
1762 /* Floating point to/from integer conversions. */
1763 { "__truncdfsf2", "__mspabi_cvtdf" },
1764 { "__extendsfdf2", "__mspabi_cvtfd" },
1765 { "__fixdfhi", "__mspabi_fixdi" },
1766 { "__fixdfsi", "__mspabi_fixdli" },
1767 { "__fixdfdi", "__mspabi_fixdlli" },
1768 { "__fixunsdfhi", "__mspabi_fixdu" },
1769 { "__fixunsdfsi", "__mspabi_fixdul" },
1770 { "__fixunsdfdi", "__mspabi_fixdull" },
1771 { "__fixsfhi", "__mspabi_fixfi" },
1772 { "__fixsfsi", "__mspabi_fixfli" },
1773 { "__fixsfdi", "__mspabi_fixflli" },
1774 { "__fixunsfhi", "__mspabi_fixfu" },
1775 { "__fixunsfsi", "__mspabi_fixful" },
1776 { "__fixunsfdi", "__mspabi_fixfull" },
1777 { "__floathisf", "__mspabi_fltif" },
1778 { "__floatsisf", "__mspabi_fltlif" },
1779 { "__floatdisf", "__mspabi_fltllif" },
1780 { "__floathidf", "__mspabi_fltid" },
1781 { "__floatsidf", "__mspabi_fltlid" },
1782 { "__floatdidf", "__mspabi_fltllid" },
1783 { "__floatunhisf", "__mspabi_fltuf" },
1784 { "__floatunsisf", "__mspabi_fltulf" },
1785 { "__floatundisf", "__mspabi_fltullf" },
1786 { "__floatunhidf", "__mspabi_fltud" },
1787 { "__floatunsidf", "__mspabi_fltuld" },
1788 { "__floatundidf", "__mspabi_fltulld" },
1790 /* Floating point comparisons. */
1791 /* GCC uses individual functions for each comparison, TI uses one
1792 compare <=> function. */
1794 /* Floating point arithmatic */
1795 { "__adddf3", "__mspabi_addd" },
1796 { "__addsf3", "__mspabi_addf" },
1797 { "__divdf3", "__mspabi_divd" },
1798 { "__divsf3", "__mspabi_divf" },
1799 { "__muldf3", "__mspabi_mpyd" },
1800 { "__mulsf3", "__mspabi_mpyf" },
1801 { "__subdf3", "__mspabi_subd" },
1802 { "__subsf3", "__mspabi_subf" },
1803 /* GCC does not use helper functions for negation */
1805 /* Integer multiply, divide, remainder. */
1806 /* Note: gcc doesn't know about hardware multiply options (yet?) */
1807 { "__mulhi3", "__mspabi_mpyi" },
1808 { "__mulsi3", "__mspabi_mpyl" },
1809 { "__muldi3", "__mspabi_mpyll" },
1811 /* Clarify signed vs unsigned first. */
1812 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
1813 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
1816 { "__divhi3", "__mspabi_divi" },
1817 { "__divsi3", "__mspabi_divli" },
1818 { "__divdi3", "__mspabi_divlli" },
1819 { "__udivhi3", "__mspabi_divu" },
1820 { "__udivsi3", "__mspabi_divlu" },
1821 { "__udivdi3", "__mspabi_divllu" },
1822 { "__modhi3", "__mspabi_remi" },
1823 { "__modsi3", "__mspabi_remli" },
1824 { "__moddi3", "__mspabi_remlli" },
1825 { "__umodhi3", "__mspabi_remu" },
1826 { "__umodsi3", "__mspabi_remul" },
1827 { "__umoddi3", "__mspabi_remull" },
1829 /* Bitwise operations. */
1830 /* Rotation - no rotation support yet. */
1831 /* Logical left shift - gcc already does these itself. */
1832 /* Arithmetic left shift - gcc already does these itself. */
1833 /* Arithmetic right shift - gcc already does these itself. */
1838 /* This function does the same as the default, but it will replace GCC
1839 function names with the MSPABI-specified ones. */
1841 msp430_output_labelref (FILE *file
, const char *name
)
1845 for (i
= 0; helper_function_name_mappings
[i
].gcc_name
; i
++)
1846 if (! strcmp (helper_function_name_mappings
[i
].gcc_name
, name
))
1848 fputs (helper_function_name_mappings
[i
].ti_name
, file
);
1855 /* Common code for msp430_print_operand... */
1858 msp430_print_operand_raw (FILE * file
, rtx op
)
1862 switch (GET_CODE (op
))
1865 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
1871 fprintf (file
, "%#" HOST_WIDE_INT_PRINT
"x", i
);
1873 fprintf (file
, "%" HOST_WIDE_INT_PRINT
"d", i
);
1881 output_addr_const (file
, op
);
1885 print_rtl (file
, op
);
1890 #undef TARGET_PRINT_OPERAND_ADDRESS
1891 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
1893 /* Output to stdio stream FILE the assembler syntax for an
1894 instruction operand that is a memory reference whose address
1898 msp430_print_operand_addr (FILE * file
, rtx addr
)
1900 switch (GET_CODE (addr
))
1903 msp430_print_operand_raw (file
, XEXP (addr
, 1));
1904 gcc_assert (REG_P (XEXP (addr
, 0)));
1905 fprintf (file
, "(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
1909 fprintf (file
, "@");
1916 fprintf (file
, "&");
1923 msp430_print_operand_raw (file
, addr
);
1926 #undef TARGET_PRINT_OPERAND
1927 #define TARGET_PRINT_OPERAND msp430_print_operand
1929 /* A low 16-bits of int/lower of register pair
1930 B high 16-bits of int/higher of register pair
1931 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
1932 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
1933 H like %B (for backwards compatibility)
1935 J an integer without a # prefix
1936 L like %A (for backwards compatibility)
1937 O offset of the top of the stack
1938 Q like X but generates an A postfix
1939 R inverse of condition code, unsigned.
1940 X X instruction postfix in large mode
1943 b .B or .W or .A, depending upon the mode
1945 r inverse of condition code
1946 x like X but only for pointers. */
1949 msp430_print_operand (FILE * file
, rtx op
, int letter
)
1953 /* We can't use c, n, a, or l. */
1957 gcc_assert (CONST_INT_P (op
));
1958 /* Print the constant value, less one. */
1959 fprintf (file
, "#%ld", INTVAL (op
) - 1);
1962 gcc_assert (CONST_INT_P (op
));
1963 /* Print the constant value, less four. */
1964 fprintf (file
, "#%ld", INTVAL (op
) - 4);
1967 if (GET_CODE (op
) == CONST_INT
)
1969 /* Inverse of constants */
1970 int i
= INTVAL (op
);
1971 fprintf (file
, "%d", ~i
);
1976 case 'r': /* Conditional jump where the condition is reversed. */
1977 switch (GET_CODE (op
))
1979 case EQ
: fprintf (file
, "NE"); break;
1980 case NE
: fprintf (file
, "EQ"); break;
1981 case GEU
: fprintf (file
, "LO"); break;
1982 case LTU
: fprintf (file
, "HS"); break;
1983 case GE
: fprintf (file
, "L"); break;
1984 case LT
: fprintf (file
, "GE"); break;
1985 /* Assume these have reversed operands. */
1986 case GTU
: fprintf (file
, "HS"); break;
1987 case LEU
: fprintf (file
, "LO"); break;
1988 case GT
: fprintf (file
, "GE"); break;
1989 case LE
: fprintf (file
, "L"); break;
1991 msp430_print_operand_raw (file
, op
);
1995 case 'R': /* Conditional jump where the operands are reversed. */
1996 switch (GET_CODE (op
))
1998 case GTU
: fprintf (file
, "LO"); break;
1999 case LEU
: fprintf (file
, "HS"); break;
2000 case GT
: fprintf (file
, "L"); break;
2001 case LE
: fprintf (file
, "GE"); break;
2003 msp430_print_operand_raw (file
, op
);
2007 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
2008 gcc_assert (CONST_INT_P (op
));
2009 fprintf (file
, "#%d", 1 << INTVAL (op
));
2012 switch (GET_MODE (op
))
2014 case QImode
: fprintf (file
, ".B"); return;
2015 case HImode
: fprintf (file
, ".W"); return;
2016 case PSImode
: fprintf (file
, ".A"); return;
2017 case SImode
: fprintf (file
, ".A"); return;
2022 case 'L': /* Low half. */
2023 switch (GET_CODE (op
))
2026 op
= adjust_address (op
, Pmode
, 0);
2031 op
= GEN_INT (INTVAL (op
) & 0xffff);
2035 /* If you get here, figure out a test case :-) */
2040 case 'H': /* high half */
2041 switch (GET_CODE (op
))
2044 op
= adjust_address (op
, Pmode
, 2);
2047 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 1);
2050 op
= GEN_INT (INTVAL (op
) >> 16);
2054 /* If you get here, figure out a test case :-) */
2059 switch (GET_CODE (op
))
2062 op
= adjust_address (op
, Pmode
, 3);
2065 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 2);
2068 op
= GEN_INT (INTVAL (op
) >> 32);
2072 /* If you get here, figure out a test case :-) */
2077 switch (GET_CODE (op
))
2080 op
= adjust_address (op
, Pmode
, 4);
2083 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 3);
2086 op
= GEN_INT (INTVAL (op
) >> 48);
2090 /* If you get here, figure out a test case :-) */
2096 /* This is used to turn, for example, an ADD opcode into an ADDX
2097 opcode when we're using 20-bit addresses. */
2099 fprintf (file
, "X");
2100 /* We don't care which operand we use, but we want 'X' in the MD
2101 file, so we do it this way. */
2105 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
2106 if (TARGET_LARGE
&& GET_MODE (op
) == PSImode
)
2107 fprintf (file
, "X");
2111 /* Likewise, for BR -> BRA. */
2113 fprintf (file
, "A");
2117 /* Computes the offset to the top of the stack for the current frame.
2118 This has to be done here rather than in, say, msp430_expand_builtin()
2119 because builtins are expanded before the frame layout is determined. */
2120 fprintf (file
, "%d",
2121 msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, STACK_POINTER_REGNUM
)
2126 gcc_assert (GET_CODE (op
) == CONST_INT
);
2130 output_operand_lossage ("invalid operand prefix");
2134 switch (GET_CODE (op
))
2137 msp430_print_operand_raw (file
, op
);
2141 addr
= XEXP (op
, 0);
2142 msp430_print_operand_addr (file
, addr
);
2150 fprintf (file
, "#");
2151 msp430_print_operand_raw (file
, op
);
2154 case EQ
: fprintf (file
, "EQ"); break;
2155 case NE
: fprintf (file
, "NE"); break;
2156 case GEU
: fprintf (file
, "HS"); break;
2157 case LTU
: fprintf (file
, "LO"); break;
2158 case GE
: fprintf (file
, "GE"); break;
2159 case LT
: fprintf (file
, "L"); break;
2162 print_rtl (file
, op
);
2171 msp430_return_addr_rtx (int count
)
2177 ra_size
= TARGET_LARGE
? 4 : 2;
2178 if (crtl
->args
.pretend_args_size
)
2181 return gen_rtx_MEM (Pmode
, gen_rtx_PLUS (Pmode
, arg_pointer_rtx
, GEN_INT (- ra_size
)));
2185 msp430_incoming_return_addr_rtx (void)
2187 return gen_rtx_MEM (Pmode
, stack_pointer_rtx
);
2190 /* Instruction generation stuff. */
2192 /* Generate a sequence of instructions to sign-extend an HI
2193 value into an SI value. Handles the tricky case where
2194 we are overwriting the destination. */
2197 msp430x_extendhisi (rtx
* operands
)
2199 if (REGNO (operands
[0]) == REGNO (operands
[1]))
2200 /* Low word of dest == source word. */
2201 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
2204 /* Note: This sequence is approximately the same length as invoking a helper
2205 function to perform the sign-extension, as in:
2209 CALL __mspabi_srai_15
2212 but this version does not involve any function calls or using argument
2213 registers, so it reduces register pressure. */
2214 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
2216 if (REGNO (operands
[0]) + 1 == REGNO (operands
[1]))
2217 /* High word of dest == source word. */
2218 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
2220 /* No overlap between dest and source. */
2221 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
2224 /* Likewise for logical right shifts. */
2226 msp430x_logical_shift_right (rtx amount
)
2228 /* The MSP430X's logical right shift instruction - RRUM - does
2229 not use an extension word, so we cannot encode a repeat count.
2230 Try various alternatives to work around this. If the count
2231 is in a register we are stuck, hence the assert. */
2232 gcc_assert (CONST_INT_P (amount
));
2234 if (INTVAL (amount
) <= 0
2235 || INTVAL (amount
) >= 16)
2236 return "# nop logical shift.";
2238 if (INTVAL (amount
) > 0
2239 && INTVAL (amount
) < 5)
2240 return "rrum.w\t%2, %0"; /* Two bytes. */
2242 if (INTVAL (amount
) > 4
2243 && INTVAL (amount
) < 9)
2244 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
2246 /* First we logically shift right by one. Now we know
2247 that the top bit is zero and we can use the arithmetic
2248 right shift instruction to perform the rest of the shift. */
2249 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
2252 struct gcc_target targetm
= TARGET_INITIALIZER
;
2254 #include "gt-msp430.h"