1 /* Subroutines used for code generation on TI MSP430 processors.
2 Copyright (C) 2012-2013 Free Software Foundation, Inc.
3 Contributed by Red Hat.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
28 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "conditions.h"
32 #include "insn-attr.h"
39 #include "diagnostic-core.h"
47 #include "target-def.h"
48 #include "langhooks.h"
49 #include "msp430-protos.h"
55 static void msp430_compute_frame_info (void);
59 /* Run-time Target Specification */
63 struct GTY(()) machine_function
65 /* If set, the rest of the fields have been computed. */
67 /* Which registers need to be saved in the pro/epilogue. */
68 int need_to_save
[FIRST_PSEUDO_REGISTER
];
70 /* These fields describe the frame layout... */
72 /* 2/4 bytes for saved PC */
76 int framesize_outgoing
;
80 /* How much we adjust the stack when returning from an exception
85 /* This is our init_machine_status, as set in
86 msp_option_override. */
87 static struct machine_function
*
88 msp430_init_machine_status (void)
90 struct machine_function
*m
;
92 m
= ggc_alloc_cleared_machine_function ();
97 #undef TARGET_HANDLE_OPTION
98 #define TARGET_HANDLE_OPTION msp430_handle_option
101 msp430_handle_option (struct gcc_options
*opts ATTRIBUTE_UNUSED
,
102 struct gcc_options
*opts_set ATTRIBUTE_UNUSED
,
103 const struct cl_decoded_option
*decoded ATTRIBUTE_UNUSED
,
104 location_t loc ATTRIBUTE_UNUSED
)
109 #undef TARGET_OPTION_OVERRIDE
110 #define TARGET_OPTION_OVERRIDE msp430_option_override
113 msp430_option_override (void)
115 init_machine_status
= msp430_init_machine_status
;
118 && (strstr (target_cpu
, "430x")
119 || strstr (target_cpu
, "430X")))
122 if (TARGET_LARGE
&& !msp430x
)
123 error ("-mlarge requires a 430X-compatible -mmcu=");
125 if (flag_exceptions
|| flag_non_call_exceptions
126 || flag_unwind_tables
|| flag_asynchronous_unwind_tables
)
127 flag_omit_frame_pointer
= false;
129 flag_omit_frame_pointer
= true;
131 /* This is a hack to work around a problem with the newlib build
132 mechanism. Newlib always appends CFLAGS to the end of the GCC
133 command line and always sets -O2 in CFLAGS. Thus it is not
134 possible to build newlib with -Os enabled. Until now... */
135 if (TARGET_OPT_SPACE
&& optimize
< 3)
143 #undef TARGET_MS_BITFIELD_LAYOUT_P
144 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
147 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED
)
156 /* Implements HARD_REGNO_NREGS. MSP430X registers can hold a single
157 PSImode value, but not an SImode value. */
159 msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED
,
160 enum machine_mode mode
)
162 if (mode
== PSImode
&& msp430x
)
164 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
168 /* Implements HARD_REGNO_MODE_OK. */
170 msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED
,
171 enum machine_mode mode
)
173 return regno
<= (ARG_POINTER_REGNUM
- msp430_hard_regno_nregs (regno
, mode
));
176 /* Implements MODES_TIEABLE_P. */
178 msp430_modes_tieable_p (enum machine_mode mode1
, enum machine_mode mode2
)
180 if ((mode1
== PSImode
|| mode2
== SImode
)
181 || (mode1
== SImode
|| mode2
== PSImode
))
184 return ((GET_MODE_CLASS (mode1
) == MODE_FLOAT
185 || GET_MODE_CLASS (mode1
) == MODE_COMPLEX_FLOAT
)
186 == (GET_MODE_CLASS (mode2
) == MODE_FLOAT
187 || GET_MODE_CLASS (mode2
) == MODE_COMPLEX_FLOAT
));
190 #undef TARGET_FRAME_POINTER_REQUIRED
191 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
194 msp430_frame_pointer_required (void)
199 #undef TARGET_CAN_ELIMINATE
200 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
203 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED
,
204 const int to_reg ATTRIBUTE_UNUSED
)
209 /* Implements INITIAL_ELIMINATION_OFFSET. */
211 msp430_initial_elimination_offset (int from
, int to
)
213 int rv
= 0; /* As if arg to arg. */
215 msp430_compute_frame_info ();
219 case STACK_POINTER_REGNUM
:
220 rv
+= cfun
->machine
->framesize_outgoing
;
221 rv
+= cfun
->machine
->framesize_locals
;
223 case FRAME_POINTER_REGNUM
:
224 rv
+= cfun
->machine
->framesize_regs
;
225 /* Allow for the saved return address. */
226 rv
+= (TARGET_LARGE
? 4 : 2);
227 /* NB/ No need to allow for crtl->args.pretend_args_size.
228 GCC does that for us. */
236 case FRAME_POINTER_REGNUM
:
237 /* Allow for the fall through above. */
238 rv
-= (TARGET_LARGE
? 4 : 2);
239 rv
-= cfun
->machine
->framesize_regs
;
240 case ARG_POINTER_REGNUM
:
249 /* Named Address Space support */
252 /* Return the appropriate mode for a named address pointer. */
253 #undef TARGET_ADDR_SPACE_POINTER_MODE
254 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
255 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
256 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
258 static enum machine_mode
259 msp430_addr_space_pointer_mode (addr_space_t addrspace
)
264 case ADDR_SPACE_GENERIC
:
266 case ADDR_SPACE_NEAR
:
273 /* Function pointers are stored in unwind_word sized
274 variables, so make sure that unwind_word is big enough. */
275 #undef TARGET_UNWIND_WORD_MODE
276 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
278 static enum machine_mode
279 msp430_unwind_word_mode (void)
281 return TARGET_LARGE
? SImode
: HImode
;
284 /* Determine if one named address space is a subset of another. */
285 #undef TARGET_ADDR_SPACE_SUBSET_P
286 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
288 msp430_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
290 if (subset
== superset
)
293 return (subset
!= ADDR_SPACE_FAR
&& superset
== ADDR_SPACE_FAR
);
296 #undef TARGET_ADDR_SPACE_CONVERT
297 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
298 /* Convert from one address space to another. */
300 msp430_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
302 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
303 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
306 if (to_as
!= ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_FAR
)
308 /* This is unpredictable, as we're truncating off usable address
312 return gen_rtx_CONST (HImode
, op
);
314 result
= gen_reg_rtx (HImode
);
315 emit_insn (gen_truncpsihi2 (result
, op
));
318 else if (to_as
== ADDR_SPACE_FAR
&& from_as
!= ADDR_SPACE_FAR
)
320 /* This always works. */
323 return gen_rtx_CONST (PSImode
, op
);
325 result
= gen_reg_rtx (PSImode
);
326 emit_insn (gen_zero_extendhipsi2 (result
, op
));
333 /* Stack Layout and Calling Conventions. */
335 /* For each function, we list the gcc version and the TI version on
336 each line, where we're converting the function names. */
337 static char const * const special_convention_function_names
[] =
339 "__muldi3", "__mspabi_mpyll",
340 "__udivdi3", "__mspabi_divull",
341 "__umoddi3", "__mspabi_remull",
342 "__divdi3", "__mspabi_divlli",
343 "__moddi3", "__mspabi_remlli",
347 "__adddf3", "__mspabi_addd",
348 "__subdf3", "__mspabi_subd",
349 "__muldf3", "__mspabi_mpyd",
350 "__divdf3", "__mspabi_divd",
355 /* TRUE if the function passed is a "speical" function. Special
356 functions pass two DImode parameters in registers. */
358 msp430_special_register_convention_p (const char *name
)
362 for (i
= 0; special_convention_function_names
[i
]; i
++)
363 if (! strcmp (name
, special_convention_function_names
[i
]))
369 #undef TARGET_FUNCTION_VALUE_REGNO_P
370 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
373 msp430_function_value_regno_p (unsigned int regno
)
379 #undef TARGET_FUNCTION_VALUE
380 #define TARGET_FUNCTION_VALUE msp430_function_value
383 msp430_function_value (const_tree ret_type
,
384 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
385 bool outgoing ATTRIBUTE_UNUSED
)
387 return gen_rtx_REG (TYPE_MODE (ret_type
), 12);
390 #undef TARGET_LIBCALL_VALUE
391 #define TARGET_LIBCALL_VALUE msp430_libcall_value
394 msp430_libcall_value (enum machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
396 return gen_rtx_REG (mode
, 12);
399 /* Implements INIT_CUMULATIVE_ARGS. */
401 msp430_init_cumulative_args (CUMULATIVE_ARGS
*ca
,
402 tree fntype ATTRIBUTE_UNUSED
,
403 rtx libname ATTRIBUTE_UNUSED
,
404 tree fndecl ATTRIBUTE_UNUSED
,
405 int n_named_args ATTRIBUTE_UNUSED
)
408 memset (ca
, 0, sizeof(*ca
));
413 fname
= IDENTIFIER_POINTER (DECL_NAME (fndecl
));
415 fname
= XSTR (libname
, 0);
419 if (fname
&& msp430_special_register_convention_p (fname
))
423 /* Helper function for argument passing; this function is the common
424 code that determines where an argument will be passed. */
426 msp430_evaluate_arg (cumulative_args_t cap
,
427 enum machine_mode mode
,
428 const_tree type ATTRIBUTE_UNUSED
,
431 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
432 int nregs
= GET_MODE_SIZE (mode
);
444 nregs
= (nregs
+ 1) / 2;
448 /* Function is passed two DImode operands, in R8:R11 and
458 for (i
= 0; i
< 4; i
++)
459 if (! ca
->reg_used
[i
])
462 ca
->start_reg
= CA_FIRST_REG
+ i
;
467 for (i
= 0; i
< 3; i
++)
468 if (! ca
->reg_used
[i
] && ! ca
->reg_used
[i
+ 1])
471 ca
->start_reg
= CA_FIRST_REG
+ i
;
474 if (! ca
->reg_used
[3] && ca
->can_split
)
478 ca
->start_reg
= CA_FIRST_REG
+ 3;
485 if (! ca
->reg_used
[0]
486 && ! ca
->reg_used
[1]
487 && ! ca
->reg_used
[2]
488 && ! ca
->reg_used
[3])
491 ca
->start_reg
= CA_FIRST_REG
;
498 #undef TARGET_PROMOTE_PROTOTYPES
499 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
502 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED
)
507 #undef TARGET_FUNCTION_ARG
508 #define TARGET_FUNCTION_ARG msp430_function_arg
511 msp430_function_arg (cumulative_args_t cap
,
512 enum machine_mode mode
,
516 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
518 msp430_evaluate_arg (cap
, mode
, type
, named
);
521 return gen_rtx_REG (mode
, ca
->start_reg
);
526 #undef TARGET_ARG_PARTIAL_BYTES
527 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
530 msp430_arg_partial_bytes (cumulative_args_t cap
,
531 enum machine_mode mode
,
535 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
537 msp430_evaluate_arg (cap
, mode
, type
, named
);
539 if (ca
->reg_count
&& ca
->mem_count
)
540 return ca
->reg_count
* UNITS_PER_WORD
;
545 #undef TARGET_PASS_BY_REFERENCE
546 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
549 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED
,
550 enum machine_mode mode
,
552 bool named ATTRIBUTE_UNUSED
)
554 return (mode
== BLKmode
555 || (type
&& TREE_CODE (type
) == RECORD_TYPE
)
556 || (type
&& TREE_CODE (type
) == UNION_TYPE
));
559 #undef TARGET_CALLEE_COPIES
560 #define TARGET_CALLEE_COPIES msp430_callee_copies
563 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED
,
564 enum machine_mode mode ATTRIBUTE_UNUSED
,
565 const_tree type ATTRIBUTE_UNUSED
,
566 bool named ATTRIBUTE_UNUSED
)
571 #undef TARGET_FUNCTION_ARG_ADVANCE
572 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
575 msp430_function_arg_advance (cumulative_args_t cap
,
576 enum machine_mode mode
,
580 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
583 msp430_evaluate_arg (cap
, mode
, type
, named
);
585 if (ca
->start_reg
>= CA_FIRST_REG
)
586 for (i
= 0; i
< ca
->reg_count
; i
++)
587 ca
->reg_used
[i
+ ca
->start_reg
- CA_FIRST_REG
] = 1;
592 #undef TARGET_FUNCTION_ARG_BOUNDARY
593 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
596 msp430_function_arg_boundary (enum machine_mode mode
, const_tree type
)
599 && int_size_in_bytes (type
) > 1)
601 if (GET_MODE_BITSIZE (mode
) > 8)
606 #undef TARGET_RETURN_IN_MEMORY
607 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
610 msp430_return_in_memory (const_tree ret_type
, const_tree fntype ATTRIBUTE_UNUSED
)
612 enum machine_mode mode
= TYPE_MODE (ret_type
);
615 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == RECORD_TYPE
)
616 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == UNION_TYPE
))
619 if (GET_MODE_SIZE (mode
) > 8)
625 #undef TARGET_GET_RAW_ARG_MODE
626 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
628 static enum machine_mode
629 msp430_get_raw_arg_mode (int regno
)
631 return (regno
== ARG_POINTER_REGNUM
) ? VOIDmode
: Pmode
;
634 #undef TARGET_GET_RAW_RESULT_MODE
635 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
637 static enum machine_mode
638 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED
)
643 /* Addressing Modes */
645 #undef TARGET_LEGITIMATE_ADDRESS_P
646 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
649 reg_ok_for_addr (rtx r
, bool strict
)
653 if (strict
&& rn
>= FIRST_PSEUDO_REGISTER
)
654 rn
= reg_renumber
[rn
];
655 if (strict
&& 0 <= rn
&& rn
< FIRST_PSEUDO_REGISTER
)
663 msp430_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED
,
664 rtx x ATTRIBUTE_UNUSED
,
665 bool strict ATTRIBUTE_UNUSED
)
667 switch (GET_CODE (x
))
673 if (REG_P (XEXP (x
, 0)))
675 if (GET_MODE (x
) != GET_MODE (XEXP (x
, 0)))
677 if (!reg_ok_for_addr (XEXP (x
, 0), strict
))
679 switch (GET_CODE (XEXP (x
, 1)))
692 if (!reg_ok_for_addr (x
, strict
))
705 #undef TARGET_LEGITIMATE_CONSTANT_P
706 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
709 msp430_legitimate_constant (enum machine_mode mode
, rtx x
)
711 return ! CONST_INT_P (x
)
713 /* GCC does not know the width of the PSImode, so make
714 sure that it does not try to use a constant value that
716 || (INTVAL (x
) < (1 << 20) && INTVAL (x
) >= (-1 << 20));
720 #undef TARGET_RTX_COSTS
721 #define TARGET_RTX_COSTS msp430_rtx_costs
723 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED
,
725 int outer_code ATTRIBUTE_UNUSED
,
726 int opno ATTRIBUTE_UNUSED
,
728 bool speed ATTRIBUTE_UNUSED
)
733 if (GET_MODE (x
) == SImode
&& outer_code
== SET
)
735 *total
= COSTS_N_INSNS (4);
744 *total
= COSTS_N_INSNS (100);
752 /* Function Entry and Exit */
754 /* The MSP430 call frame looks like this:
757 +--------------------+
761 +--------------------+ <-- "arg pointer"
763 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
765 +--------------------+
766 | SR if this func has|
767 | been called via an |
769 +--------------------+ <-- SP before prologue, also AP
771 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
773 +--------------------+ <-- "frame pointer"
777 +--------------------+
781 +--------------------+ <-- SP during function
786 /* We use this to wrap all emitted insns in the prologue, so they get
787 the "frame-related" (/f) flag set. */
791 RTX_FRAME_RELATED_P (x
) = 1;
795 /* This is the one spot that decides if a register is to be saved and
796 restored in the prologue/epilogue. */
798 msp430_preserve_reg_p (int regno
)
800 /* PC, SP, SR, and the constant generator. */
804 /* FIXME: add interrupt, EH, etc. */
805 if (crtl
->calls_eh_return
)
808 /* Shouldn't be more than the above, but just in case... */
809 if (fixed_regs
[regno
])
812 /* Interrupt handlers save all registers they use, even
813 ones which are call saved. If they call other functions
814 then *every* register is saved. */
815 if (msp430_is_interrupt_func ())
816 return ! crtl
->is_leaf
|| df_regs_ever_live_p (regno
);
818 if (!call_used_regs
[regno
]
819 && df_regs_ever_live_p (regno
))
825 /* Compute all the frame-related fields in our machine_function
828 msp430_compute_frame_info (void)
832 cfun
->machine
->computed
= 1;
833 cfun
->machine
->framesize_regs
= 0;
834 cfun
->machine
->framesize_locals
= get_frame_size ();
835 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
837 for (i
= 0; i
< ARG_POINTER_REGNUM
; i
++)
838 if (msp430_preserve_reg_p (i
))
840 cfun
->machine
->need_to_save
[i
] = 1;
841 cfun
->machine
->framesize_regs
+= (TARGET_LARGE
? 4 : 2);
844 cfun
->machine
->need_to_save
[i
] = 0;
846 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
847 cfun
->machine
->framesize_locals
++;
849 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
850 + cfun
->machine
->framesize_locals
851 + cfun
->machine
->framesize_outgoing
);
855 is_attr_func (const char * attr
)
857 return lookup_attribute (attr
, DECL_ATTRIBUTES (current_function_decl
)) != NULL_TREE
;
860 /* Returns true if the current function has the "interrupt" attribute. */
863 msp430_is_interrupt_func (void)
865 return is_attr_func ("interrupt");
871 return is_attr_func ("naked");
875 is_reentrant_func (void)
877 return is_attr_func ("reentrant");
881 is_critical_func (void)
883 return is_attr_func ("critical");
886 #undef TARGET_ASM_FUNCTION_PROLOGUE
887 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
890 msp430_start_function (FILE *outfile
, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED
)
894 fprintf (outfile
, "; start of function\n");
896 if (DECL_ATTRIBUTES (current_function_decl
) != NULL_TREE
)
898 fprintf (outfile
, "; attributes: ");
899 if (is_naked_func ())
900 fprintf (outfile
, "naked ");
901 if (msp430_is_interrupt_func ())
902 fprintf (outfile
, "interrupt ");
903 if (is_reentrant_func ())
904 fprintf (outfile
, "reentrant ");
905 if (is_critical_func ())
906 fprintf (outfile
, "critical ");
907 fprintf (outfile
, "\n");
910 fprintf (outfile
, "; framesize_regs: %d\n", cfun
->machine
->framesize_regs
);
911 fprintf (outfile
, "; framesize_locals: %d\n", cfun
->machine
->framesize_locals
);
912 fprintf (outfile
, "; framesize_outgoing: %d\n", cfun
->machine
->framesize_outgoing
);
913 fprintf (outfile
, "; framesize: %d\n", cfun
->machine
->framesize
);
914 fprintf (outfile
, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, FRAME_POINTER_REGNUM
));
915 fprintf (outfile
, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM
, STACK_POINTER_REGNUM
));
918 fprintf (outfile
, "; saved regs:");
919 for (r
= 0; r
< ARG_POINTER_REGNUM
; r
++)
920 if (cfun
->machine
->need_to_save
[r
])
922 fprintf (outfile
, " %s", reg_names
[r
]);
926 fprintf (outfile
, "(none)");
927 fprintf (outfile
, "\n");
930 /* Common code to change the stack pointer. */
932 increment_stack (HOST_WIDE_INT amount
)
935 rtx sp
= stack_pointer_rtx
;
942 inc
= GEN_INT (- amount
);
944 F (emit_insn (gen_subpsi3 (sp
, sp
, inc
)));
946 F (emit_insn (gen_subhi3 (sp
, sp
, inc
)));
950 inc
= GEN_INT (amount
);
952 emit_insn (gen_addpsi3 (sp
, sp
, inc
));
954 emit_insn (gen_addhi3 (sp
, sp
, inc
));
958 /* Verify MSP430 specific attributes. */
961 msp430_attr (tree
* node
,
964 int flags ATTRIBUTE_UNUSED
,
967 gcc_assert (DECL_P (* node
));
971 tree value
= TREE_VALUE (args
);
973 switch (TREE_CODE (value
))
976 if ( strcmp (TREE_STRING_POINTER (value
), "reset")
977 && strcmp (TREE_STRING_POINTER (value
), "nmi")
978 && strcmp (TREE_STRING_POINTER (value
), "watchdog"))
979 /* Allow the attribute to be added - the linker script
980 being used may still recognise this name. */
981 warning (OPT_Wattributes
,
982 "unrecognised interrupt vector argument of %qE attribute",
987 if (TREE_INT_CST_LOW (value
) > 31)
988 /* Allow the attribute to be added - the linker script
989 being used may still recognise this value. */
990 warning (OPT_Wattributes
,
991 "numeric argument of %qE attribute must be in range 0..31",
996 warning (OPT_Wattributes
,
997 "argument of %qE attribute is not a string constant or number",
999 *no_add_attrs
= true;
1004 if (TREE_CODE (* node
) != FUNCTION_DECL
)
1006 warning (OPT_Wattributes
,
1007 "%qE attribute only applies to functions",
1009 * no_add_attrs
= true;
1012 /* FIXME: We ought to check that the interrupt handler
1013 attribute has been applied to a void function. */
1014 /* FIXME: We should check that reentrant and critical
1015 functions are not naked and that critical functions
1016 are not reentrant. */
1021 #undef TARGET_ATTRIBUTE_TABLE
1022 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
1024 /* Table of MSP430-specific attributes. */
1025 const struct attribute_spec msp430_attribute_table
[] =
1027 /* Name min_len decl_req, fn_type_req, affects_type_identity
1028 max_len, type_req, handler. */
1029 { "interrupt", 0, 1, true, false, false, msp430_attr
, false },
1030 { "naked", 0, 0, true, false, false, msp430_attr
, false },
1031 { "reentrant", 0, 0, true, false, false, msp430_attr
, false },
1032 { "critical", 0, 0, true, false, false, msp430_attr
, false },
1033 { NULL
, 0, 0, false, false, false, NULL
, false }
1037 msp430_start_function (FILE *file
, const char *name
, tree decl
)
1041 int_attr
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl
));
1042 if (int_attr
!= NULL_TREE
)
1044 tree intr_vector
= TREE_VALUE (int_attr
);
1046 if (intr_vector
!= NULL_TREE
)
1050 intr_vector
= TREE_VALUE (intr_vector
);
1052 /* The interrupt attribute has a vector value. Turn this into a
1053 section name, switch to that section and put the address of
1054 the current function into that vector slot. Note msp430_attr()
1055 has already verified the vector name for us. */
1056 if (TREE_CODE (intr_vector
) == STRING_CST
)
1057 sprintf (buf
, "__interrupt_vector_%.80s",
1058 TREE_STRING_POINTER (intr_vector
));
1059 else /* TREE_CODE (intr_vector) == INTEGER_CST */
1060 sprintf (buf
, "__interrupt_vector_%u",
1061 (unsigned int) TREE_INT_CST_LOW (intr_vector
));
1063 switch_to_section (get_section (buf
, SECTION_CODE
, decl
));
1064 fputs ("\t.word\t", file
);
1065 assemble_name (file
, name
);
1071 switch_to_section (function_section (decl
));
1072 ASM_OUTPUT_FUNCTION_LABEL (file
, name
, decl
);
1076 msp430_function_section (tree decl
, enum node_frequency freq
, bool startup
, bool exit
)
1078 /* In large mode we must make sure that interrupt handlers are put into
1079 low memory as the vector table only accepts 16-bit addresses. */
1081 && lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl
)))
1082 return get_section (".lowtext", SECTION_CODE
| SECTION_WRITE
, decl
);
1084 /* Otherwise, use the default function section. */
1085 return default_function_section (decl
, freq
, startup
, exit
);
1088 #undef TARGET_ASM_FUNCTION_SECTION
1089 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
1093 MSP430_BUILTIN_BIC_SR
,
1094 MSP430_BUILTIN_BIS_SR
,
1098 static GTY(()) tree msp430_builtins
[(int) MSP430_BUILTIN_max
];
1101 msp430_init_builtins (void)
1103 tree void_ftype_int
= build_function_type_list (void_type_node
, integer_type_node
, NULL
);
1105 msp430_builtins
[MSP430_BUILTIN_BIC_SR
] =
1106 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int
,
1107 MSP430_BUILTIN_BIC_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
1109 msp430_builtins
[MSP430_BUILTIN_BIS_SR
] =
1110 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int
,
1111 MSP430_BUILTIN_BIS_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
1115 msp430_builtin_decl (unsigned code
, bool initialize ATTRIBUTE_UNUSED
)
1119 case MSP430_BUILTIN_BIC_SR
:
1120 case MSP430_BUILTIN_BIS_SR
:
1121 return msp430_builtins
[code
];
1123 return error_mark_node
;
1128 msp430_expand_builtin (tree exp
,
1129 rtx target ATTRIBUTE_UNUSED
,
1130 rtx subtarget ATTRIBUTE_UNUSED
,
1131 enum machine_mode mode ATTRIBUTE_UNUSED
,
1132 int ignore ATTRIBUTE_UNUSED
)
1134 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
1135 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
1136 rtx arg1
= expand_normal (CALL_EXPR_ARG (exp
, 0));
1138 if (! msp430_is_interrupt_func ())
1140 error ("MSP430 builtin functions only work inside interrupt handlers");
1144 if (! REG_P (arg1
) && ! CONSTANT_P (arg1
))
1145 arg1
= force_reg (mode
, arg1
);
1149 case MSP430_BUILTIN_BIC_SR
: emit_insn (gen_bic_SR (arg1
)); break;
1150 case MSP430_BUILTIN_BIS_SR
: emit_insn (gen_bis_SR (arg1
)); break;
1152 internal_error ("bad builtin code");
1158 #undef TARGET_INIT_BUILTINS
1159 #define TARGET_INIT_BUILTINS msp430_init_builtins
1161 #undef TARGET_EXPAND_BUILTIN
1162 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
1164 #undef TARGET_BUILTIN_DECL
1165 #define TARGET_BUILTIN_DECL msp430_builtin_decl
1168 msp430_expand_prologue (void)
1172 /* Always use stack_pointer_rtx instead of calling
1173 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
1174 that there is a single rtx representing the stack pointer,
1175 namely stack_pointer_rtx, and uses == to recognize it. */
1176 rtx sp
= stack_pointer_rtx
;
1179 if (is_naked_func ())
1182 emit_insn (gen_prologue_start_marker ());
1184 if (is_critical_func ())
1186 emit_insn (gen_push_intr_state ());
1187 emit_insn (gen_disable_interrupts ());
1189 else if (is_reentrant_func ())
1190 emit_insn (gen_disable_interrupts ());
1192 if (!cfun
->machine
->computed
)
1193 msp430_compute_frame_info ();
1195 if (flag_stack_usage_info
)
1196 current_function_static_stack_size
= cfun
->machine
->framesize
;
1198 if (crtl
->args
.pretend_args_size
)
1202 gcc_assert (crtl
->args
.pretend_args_size
== 2);
1204 p
= emit_insn (gen_grow_and_swap ());
1206 /* Document the stack decrement... */
1207 note
= F (gen_rtx_SET (Pmode
, stack_pointer_rtx
,
1208 gen_rtx_MINUS (Pmode
, stack_pointer_rtx
, GEN_INT (2))));
1209 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
1211 /* ...and the establishment of a new location for the return address. */
1212 note
= F (gen_rtx_SET (Pmode
, gen_rtx_MEM (Pmode
,
1213 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, GEN_INT (-2))),
1215 add_reg_note (p
, REG_CFA_OFFSET
, note
);
1219 for (i
= 15; i
>= 4; i
--)
1220 if (cfun
->machine
->need_to_save
[i
])
1225 for (seq
= i
- 1; seq
>= 4 && cfun
->machine
->need_to_save
[seq
]; seq
--)
1231 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
1232 p
= F (emit_insn (gen_pushm (gen_rtx_REG (Pmode
, i
),
1235 note
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (count
+ 1));
1237 XVECEXP (note
, 0, 0)
1238 = F (gen_rtx_SET (VOIDmode
,
1240 gen_rtx_PLUS (Pmode
,
1242 GEN_INT (count
* (TARGET_LARGE
? -4 : -2)))));
1244 /* *sp-- = R[i-j] */
1248 for (j
= 0; j
< count
; j
++)
1251 int ofs
= (count
- j
- 1) * (TARGET_LARGE
? 4 : 2);
1254 addr
= gen_rtx_PLUS (Pmode
, sp
, GEN_INT (ofs
));
1256 addr
= stack_pointer_rtx
;
1258 XVECEXP (note
, 0, j
+ 1) =
1259 F (gen_rtx_SET (VOIDmode
,
1260 gen_rtx_MEM (Pmode
, addr
),
1261 gen_rtx_REG (Pmode
, i
- j
)) );
1264 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
1268 F (emit_insn (gen_push (gen_rtx_REG (Pmode
, i
))));
1271 if (frame_pointer_needed
)
1272 F (emit_move_insn (gen_rtx_REG (Pmode
, FRAME_POINTER_REGNUM
), sp
));
1274 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1276 increment_stack (- fs
);
1278 emit_insn (gen_prologue_end_marker ());
1282 msp430_expand_epilogue (int is_eh
)
1288 if (is_naked_func ())
1291 if (cfun
->machine
->need_to_save
[10])
1293 /* Check for a helper function. */
1294 helper_n
= 7; /* For when the loop below never sees a match. */
1295 for (i
= 9; i
>= 4; i
--)
1296 if (!cfun
->machine
->need_to_save
[i
])
1300 if (cfun
->machine
->need_to_save
[i
])
1309 emit_insn (gen_epilogue_start_marker ());
1311 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1313 increment_stack (fs
);
1317 /* We need to add the right "SP" register save just after the
1318 regular ones, so that when we pop it off we're in the EH
1319 return frame, not this one. This overwrites our own return
1320 address, but we're not going to be returning anyway. */
1321 rtx r12
= gen_rtx_REG (Pmode
, 12);
1322 rtx (*addPmode
)(rtx
, rtx
, rtx
) = TARGET_LARGE
? gen_addpsi3
: gen_addhi3
;
1324 /* R12 will hold the new SP. */
1325 i
= cfun
->machine
->framesize_regs
;
1326 emit_move_insn (r12
, stack_pointer_rtx
);
1327 emit_insn (addPmode (r12
, r12
, EH_RETURN_STACKADJ_RTX
));
1328 emit_insn (addPmode (r12
, r12
, GEN_INT (i
)));
1329 emit_move_insn (gen_rtx_MEM (Pmode
, plus_constant (Pmode
, stack_pointer_rtx
, i
)), r12
);
1332 for (i
= 4; i
<= 15; i
++)
1333 if (cfun
->machine
->need_to_save
[i
])
1337 for (seq
= i
+ 1; seq
<= 15 && cfun
->machine
->need_to_save
[seq
]; seq
++)
1343 /* Note: With TARGET_LARGE we still use POPM as POPX.A is two
1345 Note: See the popm pattern for the explanation of the strange
1347 emit_insn (gen_popm (stack_pointer_rtx
, GEN_INT (~(seq
- 1)),
1351 else if (i
== 11 - helper_n
1352 && ! msp430_is_interrupt_func ()
1353 && ! is_reentrant_func ()
1354 && ! is_critical_func ()
1355 && crtl
->args
.pretend_args_size
== 0
1356 /* Calling the helper takes as many bytes as the POP;RET sequence. */
1360 emit_insn (gen_epilogue_helper (GEN_INT (helper_n
)));
1364 emit_insn (gen_pop (gen_rtx_REG (Pmode
, i
)));
1369 /* Also pop SP, which puts us into the EH return frame. Except
1370 that you can't "pop" sp, you have to just load it off the
1372 emit_move_insn (stack_pointer_rtx
, gen_rtx_MEM (Pmode
, stack_pointer_rtx
));
1375 if (crtl
->args
.pretend_args_size
)
1376 emit_insn (gen_swap_and_shrink ());
1378 if (is_critical_func ())
1379 emit_insn (gen_pop_intr_state ());
1380 else if (is_reentrant_func ())
1381 emit_insn (gen_enable_interrupts ());
1383 emit_jump_insn (gen_msp_return ());
1386 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
1387 m32c_emit_eh_epilogue. */
1389 msp430_eh_return_stackadj_rtx (void)
1391 if (!cfun
->machine
->eh_stack_adjust
)
1395 sa
= gen_rtx_REG (Pmode
, 15);
1396 cfun
->machine
->eh_stack_adjust
= sa
;
1398 return cfun
->machine
->eh_stack_adjust
;
1401 /* This function is called before reload, to "fix" the stack in
1402 preparation for an EH return. */
1404 msp430_expand_eh_return (rtx eh_handler
)
1406 /* These are all Pmode */
1407 rtx ap
, sa
, ra
, tmp
;
1409 ap
= arg_pointer_rtx
;
1410 sa
= msp430_eh_return_stackadj_rtx ();
1414 tmp
= gen_rtx_PLUS (Pmode
, ap
, sa
);
1415 tmp
= plus_constant (Pmode
, tmp
, TARGET_LARGE
? -4 : -2);
1416 tmp
= gen_rtx_MEM (Pmode
, tmp
);
1417 emit_move_insn (tmp
, ra
);
1420 /* This is a list of MD patterns that implement fixed-count shifts. */
1426 rtx (*genfunc
)(rtx
,rtx
);
1428 const_shift_helpers
[] =
1430 #define CSH(N,C,X,G) { "__mspabi_"N, C, X, gen_##G }
1432 CSH ("slli", 1, 1, slli_1
),
1433 CSH ("slll", 1, 1, slll_1
),
1434 CSH ("slll", 2, 1, slll_2
),
1436 CSH ("srai", 1, 0, srai_1
),
1437 CSH ("sral", 1, 0, sral_1
),
1438 CSH ("sral", 2, 0, sral_2
),
1440 CSH ("srll", 1, 0, srll_1
),
1441 CSH ("srll", 2, 1, srll_2x
),
1446 /* The MSP430 ABI defines a number of helper functions that should be
1447 used for, for example, 32-bit shifts. This function is called to
1448 emit such a function, using the table above to optimize some
1451 msp430_expand_helper (rtx
*operands
, const char *helper_name
, bool const_variants
)
1454 char *helper_const
= NULL
;
1457 enum machine_mode arg0mode
= GET_MODE (operands
[0]);
1458 enum machine_mode arg1mode
= GET_MODE (operands
[1]);
1459 enum machine_mode arg2mode
= GET_MODE (operands
[2]);
1460 int have_430x
= msp430x
? 1 : 0;
1462 if (CONST_INT_P (operands
[2]))
1466 for (i
=0; const_shift_helpers
[i
].name
; i
++)
1468 if (const_shift_helpers
[i
].need_430x
<= have_430x
1469 && strcmp (helper_name
, const_shift_helpers
[i
].name
) == 0
1470 && INTVAL (operands
[2]) == const_shift_helpers
[i
].count
)
1472 emit_insn (const_shift_helpers
[i
].genfunc (operands
[0], operands
[1]));
1478 if (arg1mode
== VOIDmode
)
1479 arg1mode
= arg0mode
;
1480 if (arg2mode
== VOIDmode
)
1481 arg2mode
= arg0mode
;
1483 if (arg1mode
== SImode
)
1490 && CONST_INT_P (operands
[2])
1491 && INTVAL (operands
[2]) >= 1
1492 && INTVAL (operands
[2]) <= 15)
1494 /* Note that the INTVAL is limited in value and length by the conditional above. */
1495 int len
= strlen (helper_name
) + 4;
1496 helper_const
= (char *) xmalloc (len
);
1497 snprintf (helper_const
, len
, "%s_%d", helper_name
, (int) INTVAL (operands
[2]));
1500 emit_move_insn (gen_rtx_REG (arg1mode
, 12),
1503 emit_move_insn (gen_rtx_REG (arg2mode
, arg2
),
1506 c
= gen_call_value_internal (gen_rtx_REG (arg0mode
, 12),
1507 gen_rtx_SYMBOL_REF (VOIDmode
, helper_const
? helper_const
: helper_name
),
1509 c
= emit_call_insn (c
);
1510 RTL_CONST_CALL_P (c
) = 1;
1513 use_regs (&f
, 12, arg1sz
);
1515 use_regs (&f
, arg2
, 1);
1516 add_function_usage_to (c
, f
);
1518 emit_move_insn (operands
[0],
1519 gen_rtx_REG (arg0mode
, 12));
1522 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
1524 msp430_fixup_compare_operands (enum machine_mode my_mode
, rtx
* operands
)
1526 /* constants we're looking for, not constants which are allowed. */
1527 int const_op_idx
= 1;
1529 if (msp430_reversible_cmp_operator (operands
[0], VOIDmode
))
1532 if (GET_CODE (operands
[const_op_idx
]) != REG
1533 && GET_CODE (operands
[const_op_idx
]) != MEM
)
1534 operands
[const_op_idx
] = copy_to_mode_reg (my_mode
, operands
[const_op_idx
]);
1537 /* Simplify_gen_subreg() doesn't handle memory references the way we
1538 need it to below, so we use this function for when we must get a
1539 valid subreg in a "natural" state. */
1541 msp430_subreg (enum machine_mode mode
, rtx r
, enum machine_mode omode
, int byte
)
1545 if (GET_CODE (r
) == SUBREG
1546 && SUBREG_BYTE (r
) == 0)
1548 rtx ireg
= SUBREG_REG (r
);
1549 enum machine_mode imode
= GET_MODE (ireg
);
1551 /* special case for (HI (SI (PSI ...), 0)) */
1552 if (imode
== PSImode
1555 rv
= gen_rtx_SUBREG (mode
, ireg
, byte
);
1557 rv
= simplify_gen_subreg (mode
, ireg
, imode
, byte
);
1559 else if (GET_CODE (r
) == MEM
)
1560 rv
= adjust_address (r
, mode
, byte
);
1562 rv
= simplify_gen_subreg (mode
, r
, omode
, byte
);
1570 /* Called by movsi_x to generate the HImode operands. */
1572 msp430_split_movsi (rtx
*operands
)
1574 rtx op00
, op02
, op10
, op12
;
1576 op00
= msp430_subreg (HImode
, operands
[0], SImode
, 0);
1577 op02
= msp430_subreg (HImode
, operands
[0], SImode
, 2);
1579 if (GET_CODE (operands
[1]) == CONST
1580 || GET_CODE (operands
[1]) == SYMBOL_REF
)
1582 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
1583 op10
= gen_rtx_CONST (HImode
, op10
);
1584 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
1585 op12
= gen_rtx_CONST (HImode
, op12
);
1589 op10
= msp430_subreg (HImode
, operands
[1], SImode
, 0);
1590 op12
= msp430_subreg (HImode
, operands
[1], SImode
, 2);
1593 if (rtx_equal_p (operands
[0], operands
[1]))
1600 else if (rtx_equal_p (op00
, op12
)
1601 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
1602 || (REG_P (op00
) && reg_mentioned_p (op00
, op10
))
1603 /* Or storing (rN) into mem (rN). */
1604 || (REG_P (op10
) && reg_mentioned_p (op10
, op00
))
1622 /* The MSPABI specifies the names of various helper functions, many of
1623 which are compatible with GCC's helpers. This table maps the GCC
1624 name to the MSPABI name. */
1627 char const * const gcc_name
;
1628 char const * const ti_name
;
1630 helper_function_name_mappings
[] =
1632 /* Floating point to/from integer conversions. */
1633 { "__truncdfsf2", "__mspabi_cvtdf" },
1634 { "__extendsfdf2", "__mspabi_cvtfd" },
1635 { "__fixdfhi", "__mspabi_fixdi" },
1636 { "__fixdfsi", "__mspabi_fixdli" },
1637 { "__fixdfdi", "__mspabi_fixdlli" },
1638 { "__fixunsdfhi", "__mspabi_fixdu" },
1639 { "__fixunsdfsi", "__mspabi_fixdul" },
1640 { "__fixunsdfdi", "__mspabi_fixdull" },
1641 { "__fixsfhi", "__mspabi_fixfi" },
1642 { "__fixsfsi", "__mspabi_fixfli" },
1643 { "__fixsfdi", "__mspabi_fixflli" },
1644 { "__fixunsfhi", "__mspabi_fixfu" },
1645 { "__fixunsfsi", "__mspabi_fixful" },
1646 { "__fixunsfdi", "__mspabi_fixfull" },
1647 { "__floathisf", "__mspabi_fltif" },
1648 { "__floatsisf", "__mspabi_fltlif" },
1649 { "__floatdisf", "__mspabi_fltllif" },
1650 { "__floathidf", "__mspabi_fltid" },
1651 { "__floatsidf", "__mspabi_fltlid" },
1652 { "__floatdidf", "__mspabi_fltllid" },
1653 { "__floatunhisf", "__mspabi_fltuf" },
1654 { "__floatunsisf", "__mspabi_fltulf" },
1655 { "__floatundisf", "__mspabi_fltullf" },
1656 { "__floatunhidf", "__mspabi_fltud" },
1657 { "__floatunsidf", "__mspabi_fltuld" },
1658 { "__floatundidf", "__mspabi_fltulld" },
1660 /* Floating point comparisons. */
1661 /* GCC uses individual functions for each comparison, TI uses one
1662 compare <=> function. */
1664 /* Floating point arithmatic */
1665 { "__adddf3", "__mspabi_addd" },
1666 { "__addsf3", "__mspabi_addf" },
1667 { "__divdf3", "__mspabi_divd" },
1668 { "__divsf3", "__mspabi_divf" },
1669 { "__muldf3", "__mspabi_mpyd" },
1670 { "__mulsf3", "__mspabi_mpyf" },
1671 { "__subdf3", "__mspabi_subd" },
1672 { "__subsf3", "__mspabi_subf" },
1673 /* GCC does not use helper functions for negation */
1675 /* Integer multiply, divide, remainder. */
1676 /* Note: gcc doesn't know about hardware multiply options (yet?) */
1677 { "__mulhi3", "__mspabi_mpyi" },
1678 { "__mulsi3", "__mspabi_mpyl" },
1679 { "__muldi3", "__mspabi_mpyll" },
1681 /* Clarify signed vs unsigned first. */
1682 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
1683 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
1686 { "__divhi3", "__mspabi_divi" },
1687 { "__divsi3", "__mspabi_divli" },
1688 { "__divdi3", "__mspabi_divlli" },
1689 { "__udivhi3", "__mspabi_divu" },
1690 { "__udivsi3", "__mspabi_divlu" },
1691 { "__udivdi3", "__mspabi_divllu" },
1692 { "__modhi3", "__mspabi_remi" },
1693 { "__modsi3", "__mspabi_remli" },
1694 { "__moddi3", "__mspabi_remlli" },
1695 { "__umodhi3", "__mspabi_remu" },
1696 { "__umodsi3", "__mspabi_remul" },
1697 { "__umoddi3", "__mspabi_remull" },
1699 /* Bitwise operations. */
1700 /* Rotation - no rotation support yet. */
1701 /* Logical left shift - gcc already does these itself. */
1702 /* Arithmetic left shift - gcc already does these itself. */
1703 /* Arithmetic right shift - gcc already does these itself. */
1708 /* This function does the same as the default, but it will replace GCC
1709 function names with the MSPABI-specified ones. */
1711 msp430_output_labelref (FILE *file
, const char *name
)
1715 for (i
= 0; helper_function_name_mappings
[i
].gcc_name
; i
++)
1716 if (! strcmp (helper_function_name_mappings
[i
].gcc_name
, name
))
1718 fputs (helper_function_name_mappings
[i
].ti_name
, file
);
1725 /* Common code for msp430_print_operand... */
1728 msp430_print_operand_raw (FILE * file
, rtx op
)
1732 switch (GET_CODE (op
))
1735 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
1741 fprintf (file
, "%#x", i
);
1743 fprintf (file
, "%d", i
);
1751 output_addr_const (file
, op
);
1755 print_rtl (file
, op
);
1760 #undef TARGET_PRINT_OPERAND_ADDRESS
1761 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
1763 /* Output to stdio stream FILE the assembler syntax for an
1764 instruction operand that is a memory reference whose address
1768 msp430_print_operand_addr (FILE * file
, rtx addr
)
1770 switch (GET_CODE (addr
))
1773 msp430_print_operand_raw (file
, XEXP (addr
, 1));
1774 gcc_assert (REG_P (XEXP (addr
, 0)));
1775 fprintf (file
, "(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
1779 fprintf (file
, "@");
1786 fprintf (file
, "&");
1793 msp430_print_operand_raw (file
, addr
);
1796 #undef TARGET_PRINT_OPERAND
1797 #define TARGET_PRINT_OPERAND msp430_print_operand
1800 msp430_print_operand (FILE * file
, rtx op
, int letter
)
1804 /* We can't use c, n, a, or l. */
1808 gcc_assert (CONST_INT_P (op
));
1809 /* Print the constant value, less one. */
1810 fprintf (file
, "#%ld", INTVAL (op
) - 1);
1813 gcc_assert (CONST_INT_P (op
));
1814 /* Print the constant value, less four. */
1815 fprintf (file
, "#%ld", INTVAL (op
) - 4);
1817 /* case 'D': used for "decimal without '#'" */
1819 if (GET_CODE (op
) == CONST_INT
)
1821 /* Inverse of constants */
1822 int i
= INTVAL (op
);
1823 fprintf (file
, "%d", ~i
);
1828 case 'r': /* Conditional jump where the condition is reversed. */
1829 switch (GET_CODE (op
))
1831 case EQ
: fprintf (file
, "NE"); break;
1832 case NE
: fprintf (file
, "EQ"); break;
1833 case GEU
: fprintf (file
, "LO"); break;
1834 case LTU
: fprintf (file
, "HS"); break;
1835 case GE
: fprintf (file
, "L"); break;
1836 case LT
: fprintf (file
, "GE"); break;
1837 /* Assume these have reversed operands. */
1838 case GTU
: fprintf (file
, "HS"); break;
1839 case LEU
: fprintf (file
, "LO"); break;
1840 case GT
: fprintf (file
, "GE"); break;
1841 case LE
: fprintf (file
, "L"); break;
1843 msp430_print_operand_raw (file
, op
);
1847 case 'R': /* Conditional jump where the operands are reversed. */
1848 switch (GET_CODE (op
))
1850 case GTU
: fprintf (file
, "LO"); break;
1851 case LEU
: fprintf (file
, "HS"); break;
1852 case GT
: fprintf (file
, "L"); break;
1853 case LE
: fprintf (file
, "GE"); break;
1855 msp430_print_operand_raw (file
, op
);
1859 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
1860 gcc_assert (CONST_INT_P (op
));
1861 fprintf (file
, "#%d", 1 << INTVAL (op
));
1864 switch (GET_MODE (op
))
1866 case QImode
: fprintf (file
, ".B"); return;
1867 case HImode
: fprintf (file
, ".W"); return;
1868 case PSImode
: fprintf (file
, ".A"); return;
1869 case SImode
: fprintf (file
, ".A"); return;
1873 case 'L': /* Low half. */
1874 switch (GET_CODE (op
))
1877 op
= adjust_address (op
, Pmode
, 0);
1882 op
= GEN_INT (INTVAL (op
) & 0xffff);
1886 /* If you get here, figure out a test case :-) */
1890 case 'H': /* high half */
1891 switch (GET_CODE (op
))
1894 op
= adjust_address (op
, Pmode
, 2);
1897 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 1);
1900 op
= GEN_INT (INTVAL (op
) >> 16);
1904 /* If you get here, figure out a test case :-) */
1910 /* This is used to turn, for example, an ADD opcode into an ADDX
1911 opcode when we're using 20-bit addresses. */
1913 fprintf (file
, "X");
1914 /* We don't care which operand we use, but we want 'X' in the MD
1915 file, so we do it this way. */
1919 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
1920 if (TARGET_LARGE
&& GET_MODE (op
) == PSImode
)
1921 fprintf (file
, "X");
1925 /* Likewise, for BR -> BRA. */
1927 fprintf (file
, "A");
1931 /* Computes the offset to the top of the stack for the current frame.
1932 This has to be done here rather than in, say, msp430_expand_builtin()
1933 because builtins are expanded before the frame layout is determined. */
1934 fprintf (file
, "%d",
1935 msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, STACK_POINTER_REGNUM
)
1940 switch (GET_CODE (op
))
1943 msp430_print_operand_raw (file
, op
);
1947 addr
= XEXP (op
, 0);
1948 msp430_print_operand_addr (file
, addr
);
1956 fprintf (file
, "#");
1957 msp430_print_operand_raw (file
, op
);
1960 case EQ
: fprintf (file
, "EQ"); break;
1961 case NE
: fprintf (file
, "NE"); break;
1962 case GEU
: fprintf (file
, "HS"); break;
1963 case LTU
: fprintf (file
, "LO"); break;
1964 case GE
: fprintf (file
, "GE"); break;
1965 case LT
: fprintf (file
, "L"); break;
1968 print_rtl (file
, op
);
1977 msp430_return_addr_rtx (int count
)
1983 ra_size
= TARGET_LARGE
? 4 : 2;
1984 if (crtl
->args
.pretend_args_size
)
1987 return gen_rtx_MEM (Pmode
, gen_rtx_PLUS (Pmode
, arg_pointer_rtx
, GEN_INT (- ra_size
)));
1991 msp430_incoming_return_addr_rtx (void)
1993 return gen_rtx_MEM (Pmode
, stack_pointer_rtx
);
1996 /* Instruction generation stuff. */
1998 /* Generate a sequence of instructions to sign-extend an HI
1999 value into an SI value. Handles the tricky case where
2000 we are overwriting the destination. */
2003 msp430x_extendhisi (rtx
* operands
)
2005 if (REGNO (operands
[0]) == REGNO (operands
[1]))
2006 /* Low word of dest == source word. */
2007 return "BIT.W #0x8000, %L0 { SUBC.W %H0, %H0 { INV.W %H0, %H0"; /* 8-bytes. */
2010 /* Note: This sequence is approximately the same length as invoking a helper
2011 function to perform the sign-extension, as in:
2015 CALL __mspabi_srai_15
2018 but this version does not involve any function calls or using argument
2019 registers, so it reduces register pressure. */
2020 return "MOV.W %1, %L0 { BIT.W #0x8000, %L0 { SUBC.W %H0, %H0 { INV.W %H0, %H0"; /* 10-bytes. */
2022 if (REGNO (operands
[0]) + 1 == REGNO (operands
[1]))
2023 /* High word of dest == source word. */
2024 return "MOV.W %1, %L0 { RPT #15 { RRAX.W %H0"; /* 6-bytes. */
2026 /* No overlap between dest and source. */
2027 return "MOV.W %1, %L0 { MOV.W %1, %H0 { RPT #15 { RRAX.W %H0"; /* 8-bytes. */
2030 /* Likewise for logical right shifts. */
2032 msp430x_logical_shift_right (rtx amount
)
2034 /* The MSP430X's logical right shift instruction - RRUM - does
2035 not use an extension word, so we cannot encode a repeat count.
2036 Try various alternatives to work around this. If the count
2037 is in a register we are stuck, hence the assert. */
2038 gcc_assert (CONST_INT_P (amount
));
2040 if (INTVAL (amount
) <= 0
2041 || INTVAL (amount
) >= 16)
2042 return "# nop logical shift.";
2044 if (INTVAL (amount
) > 0
2045 && INTVAL (amount
) < 5)
2046 return "rrum.w\t%2, %0"; /* Two bytes. */
2048 if (INTVAL (amount
) > 4
2049 && INTVAL (amount
) < 9)
2050 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
2052 /* First we logically shift right by one. Now we know
2053 that the top bit is zero and we can use the arithmetic
2054 right shift instruction to perform the rest of the shift. */
2055 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
2058 struct gcc_target targetm
= TARGET_INITIALIZER
;
2060 #include "gt-msp430.h"