]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/msp430/msp430.c
Add generic support for noinit attribute.
[thirdparty/gcc.git] / gcc / config / msp430 / msp430.c
CommitLineData
e4a25868 1/* Subroutines used for code generation on TI MSP430 processors.
fbd26352 2 Copyright (C) 2012-2019 Free Software Foundation, Inc.
e4a25868 3 Contributed by Red Hat.
4
5 This file is part of GCC.
6
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)
10 any later version.
11
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.
16
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/>. */
20
785790dc 21#define IN_TARGET_CODE 1
22
e4a25868 23#include "config.h"
24#include "system.h"
25#include "coretypes.h"
9ef16211 26#include "backend.h"
c1eb80de 27#include "target.h"
9ef16211 28#include "rtl.h"
c1eb80de 29#include "tree.h"
30a86690 30#include "stringpool.h"
31#include "attribs.h"
c1eb80de 32#include "gimple-expr.h"
9ef16211 33#include "df.h"
ad7b10a2 34#include "memmodel.h"
c1eb80de 35#include "tm_p.h"
36#include "regs.h"
37#include "emit-rtl.h"
38#include "diagnostic-core.h"
b20a8bb4 39#include "fold-const.h"
9ed99284 40#include "stor-layout.h"
41#include "calls.h"
e4a25868 42#include "output.h"
d53441c8 43#include "explow.h"
e4a25868 44#include "expr.h"
e4a25868 45#include "langhooks.h"
f7715905 46#include "builtins.h"
f6e4a711 47#include "intl.h"
bb4cc462 48#include "msp430-devices.h"
4b498588 49
0c71fb4f 50/* This file should be included last. */
4b498588 51#include "target-def.h"
e4a25868 52\f
53
54static void msp430_compute_frame_info (void);
55
56\f
57
6956ee35 58/* Run-time Target Specification. */
e4a25868 59
6956ee35 60bool msp430x = true;
e4a25868 61
62struct GTY(()) machine_function
63{
64 /* If set, the rest of the fields have been computed. */
65 int computed;
66 /* Which registers need to be saved in the pro/epilogue. */
67 int need_to_save [FIRST_PSEUDO_REGISTER];
68
69 /* These fields describe the frame layout... */
70 /* arg pointer */
71 /* 2/4 bytes for saved PC */
72 int framesize_regs;
73 /* frame pointer */
74 int framesize_locals;
75 int framesize_outgoing;
76 /* stack pointer */
77 int framesize;
78
79 /* How much we adjust the stack when returning from an exception
80 handler. */
81 rtx eh_stack_adjust;
82};
83
84/* This is our init_machine_status, as set in
85 msp_option_override. */
86static struct machine_function *
87msp430_init_machine_status (void)
88{
89 struct machine_function *m;
90
25a27413 91 m = ggc_cleared_alloc<machine_function> ();
e4a25868 92
93 return m;
94}
95
e4a25868 96#undef TARGET_OPTION_OVERRIDE
97#define TARGET_OPTION_OVERRIDE msp430_option_override
98
8e246851 99/* Generate a C preprocessor symbol based upon the MCU selected by the user.
100 If a specific MCU has not been selected then return a generic symbol instead. */
101
102const char *
103msp430_mcu_name (void)
104{
abe1609f 105 if (target_mcu)
8e246851 106 {
bb4cc462 107 msp430_extract_mcu_data (target_mcu);
8e246851 108 unsigned int i;
b9d93755 109 unsigned int start_upper;
110 unsigned int end_upper;
111 static char mcu_name[64];
8e246851 112
b9d93755 113 /* The 'i' in the device name symbol for msp430i* devices must be lower
114 case, to match the expected symbol in msp430.h. */
115 if (strncmp (target_mcu, "msp430i", 7) == 0)
116 {
117 snprintf (mcu_name, sizeof (mcu_name) - 1, "__MSP430i%s__",
118 target_mcu + 7);
119 start_upper = 9;
120 }
121 else
122 {
123 snprintf (mcu_name, sizeof (mcu_name) - 1, "__%s__", target_mcu);
124 start_upper = 2;
125 }
126 end_upper = strlen (mcu_name) - 2;
127 for (i = start_upper; i < end_upper; i++)
8e246851 128 mcu_name[i] = TOUPPER (mcu_name[i]);
129 return mcu_name;
130 }
0a9aab6d 131
8e246851 132 return msp430x ? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
133}
134
7ed86ba5 135static const char *
136hwmult_name (unsigned int val)
137{
138 switch (val)
139 {
140 case 0: return "none";
141 case 1: return "16-bit";
142 case 2: return "16-bit";
143 case 4: return "32-bit";
144 case 8: return "32-bit (5xx)";
145 default: gcc_unreachable ();
146 }
147}
148
e4a25868 149static void
150msp430_option_override (void)
151{
427480be 152 /* The MSP430 architecture can safely dereference a NULL pointer. In fact,
153 there are memory mapped registers there. */
154 flag_delete_null_pointer_checks = 0;
155
e4a25868 156 init_machine_status = msp430_init_machine_status;
157
1b80b2b4 158 if (target_cpu)
abe1609f 159 {
7ed86ba5 160 /* gcc/common/config/msp430-common.c will have
161 already canonicalised the string in target_cpu. */
c05cbf30 162 if (strcasecmp (target_cpu, "msp430x") == 0)
abe1609f 163 msp430x = true;
c05cbf30 164 else /* target_cpu == "msp430" - already handled by the front end. */
6956ee35 165 msp430x = false;
abe1609f 166 }
7ed86ba5 167
168 if (target_mcu)
1b80b2b4 169 {
bb4cc462 170 msp430_extract_mcu_data (target_mcu);
1b80b2b4 171
bb4cc462 172 if (extracted_mcu_data.name != NULL)
c05cbf30 173 {
bb4cc462 174 bool xisa = extracted_mcu_data.revision >= 1;
7ed86ba5 175
176 if (msp430_warn_mcu)
177 {
bb4cc462 178 if (target_cpu && msp430x != xisa)
a0b58a70 179 warning (0, "MCU %qs supports %s ISA but %<-mcpu%> option "
2f6d557f 180 "is set to %s",
7ed86ba5 181 target_mcu, xisa ? "430X" : "430", msp430x ? "430X" : "430");
182
bb4cc462 183 if (extracted_mcu_data.hwmpy == 0
bdc549ca 184 && msp430_hwmult_type != MSP430_HWMULT_AUTO
185 && msp430_hwmult_type != MSP430_HWMULT_NONE)
a0b58a70 186 warning (0, "MCU %qs does not have hardware multiply "
2f6d557f 187 "support, but %<-mhwmult%> is set to %s",
7ed86ba5 188 target_mcu,
bdc549ca 189 msp430_hwmult_type == MSP430_HWMULT_SMALL ? "16-bit"
190 : msp430_hwmult_type == MSP430_HWMULT_LARGE ? "32-bit" : "f5series");
191 else if (msp430_hwmult_type == MSP430_HWMULT_SMALL
bb4cc462 192 && extracted_mcu_data.hwmpy != 1
193 && extracted_mcu_data.hwmpy != 2)
a0b58a70 194 warning (0, "MCU %qs supports %s hardware multiply, "
2f6d557f 195 "but %<-mhwmult%> is set to 16-bit",
bb4cc462 196 target_mcu, hwmult_name (extracted_mcu_data.hwmpy));
197 else if (msp430_hwmult_type == MSP430_HWMULT_LARGE
198 && extracted_mcu_data.hwmpy != 4)
a0b58a70 199 warning (0, "MCU %qs supports %s hardware multiply, "
2f6d557f 200 "but %<-mhwmult%> is set to 32-bit",
bb4cc462 201 target_mcu, hwmult_name (extracted_mcu_data.hwmpy));
202 else if (msp430_hwmult_type == MSP430_HWMULT_F5SERIES
203 && extracted_mcu_data.hwmpy != 8)
a0b58a70 204 warning (0, "MCU %qs supports %s hardware multiply, "
2f6d557f 205 "but %<-mhwmult%> is set to f5series",
bb4cc462 206 target_mcu, hwmult_name (extracted_mcu_data.hwmpy));
7ed86ba5 207 }
7ed86ba5 208 msp430x = xisa;
c05cbf30 209 }
bb4cc462 210 else
02059be0 211 {
bdc549ca 212 if (msp430_hwmult_type == MSP430_HWMULT_AUTO)
7ed86ba5 213 {
214 if (msp430_warn_mcu)
215 {
216 if (target_cpu == NULL)
217 warning (0,
a0b58a70 218 "Unrecognized MCU name %qs, assuming that it is "
d0abd9e0 219 "just a MSP430 with no hardware multiply.\n"
2f6d557f 220 "Use the %<-mcpu%> and %<-mhwmult%> options to "
221 "set these explicitly.",
7ed86ba5 222 target_mcu);
223 else
224 warning (0,
a0b58a70 225 "Unrecognized MCU name %qs, assuming that it "
2f6d557f 226 "has no hardware multiply.\nUse the %<-mhwmult%> "
d0abd9e0 227 "option to set this explicitly.",
7ed86ba5 228 target_mcu);
229 }
230
bdc549ca 231 msp430_hwmult_type = MSP430_HWMULT_NONE;
7ed86ba5 232 }
233 else if (target_cpu == NULL)
234 {
235 if (msp430_warn_mcu)
236 warning (0,
a0b58a70 237 "Unrecognized MCU name %qs, assuming that it just "
2f6d557f 238 "supports the MSP430 ISA.\nUse the %<-mcpu%> option "
239 "to set the ISA explicitly.",
7ed86ba5 240 target_mcu);
241
242 msp430x = false;
243 }
244 else if (msp430_warn_mcu)
a0b58a70 245 warning (0, "Unrecognized MCU name %qs.", target_mcu);
02059be0 246 }
1b80b2b4 247 }
e4a25868 248
7ed86ba5 249 /* The F5 series are all able to support the 430X ISA. */
bdc549ca 250 if (target_cpu == NULL && target_mcu == NULL && msp430_hwmult_type == MSP430_HWMULT_F5SERIES)
7ed86ba5 251 msp430x = true;
252
e4a25868 253 if (TARGET_LARGE && !msp430x)
2f6d557f 254 error ("%<-mlarge%> requires a 430X-compatible %<-mmcu=%>");
e4a25868 255
4b12180b 256 if (!TARGET_LARGE && msp430_code_region == MSP430_REGION_EITHER)
257 error ("%<-mcode-region=either%> requires the large memory model "
258 "(%<-mlarge%>)");
259 else if (!TARGET_LARGE && msp430_code_region == MSP430_REGION_UPPER)
260 error ("%<-mcode-region=upper%> requires the large memory model "
261 "(%<-mlarge%>)");
262 else if (!TARGET_LARGE && msp430_code_region == MSP430_REGION_LOWER)
263 error ("%<-mcode-region=lower%> requires the large memory model "
264 "(%<-mlarge%>)");
265
266 if (!TARGET_LARGE && msp430_data_region == MSP430_REGION_EITHER)
267 error ("%<-mdata-region=either%> requires the large memory model "
268 "(%<-mlarge%>)");
269 else if (!TARGET_LARGE && msp430_data_region == MSP430_REGION_UPPER)
270 error ("%<-mdata-region=upper%> requires the large memory model "
271 "(%<-mlarge%>)");
272 else if (!TARGET_LARGE && msp430_data_region == MSP430_REGION_LOWER)
273 error ("%<-mdata-region=lower%> requires the large memory model "
274 "(%<-mlarge%>)");
275
ab9c90cd 276
e4a25868 277 if (flag_exceptions || flag_non_call_exceptions
278 || flag_unwind_tables || flag_asynchronous_unwind_tables)
279 flag_omit_frame_pointer = false;
280 else
281 flag_omit_frame_pointer = true;
282
283 /* This is a hack to work around a problem with the newlib build
284 mechanism. Newlib always appends CFLAGS to the end of the GCC
285 command line and always sets -O2 in CFLAGS. Thus it is not
286 possible to build newlib with -Os enabled. Until now... */
287 if (TARGET_OPT_SPACE && optimize < 3)
288 optimize_size = 1;
289}
290
f6bba390 291#undef TARGET_SCALAR_MODE_SUPPORTED_P
292#define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
293
294static bool
8aec1ebb 295msp430_scalar_mode_supported_p (scalar_mode m)
f6bba390 296{
297 if (m == PSImode && msp430x)
298 return true;
299#if 0
300 if (m == TImode)
301 return true;
302#endif
303 return default_scalar_mode_supported_p (m);
304}
305
e4a25868 306\f
307
308/* Storage Layout */
309
310#undef TARGET_MS_BITFIELD_LAYOUT_P
311#define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
312
313bool
314msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED)
315{
316 return false;
317}
318
319\f
320
321/* Register Usage */
322
74f68e49 323#undef TARGET_HARD_REGNO_NREGS
324#define TARGET_HARD_REGNO_NREGS msp430_hard_regno_nregs
325
326static unsigned int
327msp430_hard_regno_nregs (unsigned int, machine_mode mode)
e4a25868 328{
329 if (mode == PSImode && msp430x)
330 return 1;
dff73565 331 if (mode == CPSImode && msp430x)
332 return 2;
e4a25868 333 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
334 / UNITS_PER_WORD);
335}
336
f6bba390 337/* Implements HARD_REGNO_NREGS_HAS_PADDING. */
338int
339msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED,
3754d046 340 machine_mode mode)
f6bba390 341{
342 if (mode == PSImode && msp430x)
343 return 1;
344 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
345 / UNITS_PER_WORD);
346}
347
348/* Implements HARD_REGNO_NREGS_WITH_PADDING. */
349int
350msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED,
3754d046 351 machine_mode mode)
f6bba390 352{
353 if (mode == PSImode)
354 return 2;
dff73565 355 if (mode == CPSImode)
356 return 4;
f6bba390 357 return msp430_hard_regno_nregs (regno, mode);
358}
359
b395382f 360#undef TARGET_HARD_REGNO_MODE_OK
361#define TARGET_HARD_REGNO_MODE_OK msp430_hard_regno_mode_ok
362
363static bool
364msp430_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
e4a25868 365{
b395382f 366 return regno <= (ARG_POINTER_REGNUM
367 - (unsigned int) msp430_hard_regno_nregs (regno, mode));
e4a25868 368}
369
5f6dcf1a 370#undef TARGET_MODES_TIEABLE_P
371#define TARGET_MODES_TIEABLE_P msp430_modes_tieable_p
372
373static bool
3754d046 374msp430_modes_tieable_p (machine_mode mode1, machine_mode mode2)
e4a25868 375{
376 if ((mode1 == PSImode || mode2 == SImode)
377 || (mode1 == SImode || mode2 == PSImode))
378 return false;
379
380 return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
381 || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
382 == (GET_MODE_CLASS (mode2) == MODE_FLOAT
383 || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
384}
385
386#undef TARGET_FRAME_POINTER_REQUIRED
387#define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
388
389static bool
390msp430_frame_pointer_required (void)
391{
392 return false;
393}
394
395#undef TARGET_CAN_ELIMINATE
396#define TARGET_CAN_ELIMINATE msp430_can_eliminate
397
398static bool
399msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED,
400 const int to_reg ATTRIBUTE_UNUSED)
401{
402 return true;
403}
404
405/* Implements INITIAL_ELIMINATION_OFFSET. */
406int
62b2ccbe 407msp430_initial_elimination_offset (int from, int to)
e4a25868 408{
62b2ccbe 409 int rv = 0; /* As if arg to arg. */
e4a25868 410
411 msp430_compute_frame_info ();
412
413 switch (to)
414 {
415 case STACK_POINTER_REGNUM:
416 rv += cfun->machine->framesize_outgoing;
417 rv += cfun->machine->framesize_locals;
418 /* Fall through. */
419 case FRAME_POINTER_REGNUM:
420 rv += cfun->machine->framesize_regs;
421 /* Allow for the saved return address. */
422 rv += (TARGET_LARGE ? 4 : 2);
423 /* NB/ No need to allow for crtl->args.pretend_args_size.
424 GCC does that for us. */
425 break;
426 default:
427 gcc_unreachable ();
428 }
429
430 switch (from)
431 {
432 case FRAME_POINTER_REGNUM:
433 /* Allow for the fall through above. */
434 rv -= (TARGET_LARGE ? 4 : 2);
435 rv -= cfun->machine->framesize_regs;
436 case ARG_POINTER_REGNUM:
437 break;
438 default:
439 gcc_unreachable ();
440 }
441
442 return rv;
443}
444\f
445/* Named Address Space support */
446
447
448/* Return the appropriate mode for a named address pointer. */
449#undef TARGET_ADDR_SPACE_POINTER_MODE
450#define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
451#undef TARGET_ADDR_SPACE_ADDRESS_MODE
452#define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
453
f77c4496 454static scalar_int_mode
e4a25868 455msp430_addr_space_pointer_mode (addr_space_t addrspace)
456{
457 switch (addrspace)
458 {
459 default:
460 case ADDR_SPACE_GENERIC:
461 return Pmode;
462 case ADDR_SPACE_NEAR:
463 return HImode;
464 case ADDR_SPACE_FAR:
465 return PSImode;
466 }
467}
468
469/* Function pointers are stored in unwind_word sized
470 variables, so make sure that unwind_word is big enough. */
471#undef TARGET_UNWIND_WORD_MODE
472#define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
473
f77c4496 474static scalar_int_mode
e4a25868 475msp430_unwind_word_mode (void)
476{
7ed86ba5 477 /* This needs to match msp430_init_dwarf_reg_sizes_extra (below). */
478 return msp430x ? PSImode : HImode;
e4a25868 479}
480
481/* Determine if one named address space is a subset of another. */
482#undef TARGET_ADDR_SPACE_SUBSET_P
483#define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
484static bool
485msp430_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
486{
487 if (subset == superset)
488 return true;
489 else
490 return (subset != ADDR_SPACE_FAR && superset == ADDR_SPACE_FAR);
491}
492
493#undef TARGET_ADDR_SPACE_CONVERT
494#define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
495/* Convert from one address space to another. */
496static rtx
497msp430_addr_space_convert (rtx op, tree from_type, tree to_type)
498{
499 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
500 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
501 rtx result;
502
503 if (to_as != ADDR_SPACE_FAR && from_as == ADDR_SPACE_FAR)
504 {
505 /* This is unpredictable, as we're truncating off usable address
506 bits. */
507
508 if (CONSTANT_P (op))
509 return gen_rtx_CONST (HImode, op);
510
511 result = gen_reg_rtx (HImode);
512 emit_insn (gen_truncpsihi2 (result, op));
513 return result;
514 }
515 else if (to_as == ADDR_SPACE_FAR && from_as != ADDR_SPACE_FAR)
516 {
517 /* This always works. */
518
519 if (CONSTANT_P (op))
520 return gen_rtx_CONST (PSImode, op);
521
522 result = gen_reg_rtx (PSImode);
523 emit_insn (gen_zero_extendhipsi2 (result, op));
524 return result;
525 }
526 else
527 gcc_unreachable ();
528}
529\f
530/* Stack Layout and Calling Conventions. */
531
532/* For each function, we list the gcc version and the TI version on
533 each line, where we're converting the function names. */
534static char const * const special_convention_function_names [] =
535{
536 "__muldi3", "__mspabi_mpyll",
537 "__udivdi3", "__mspabi_divull",
538 "__umoddi3", "__mspabi_remull",
539 "__divdi3", "__mspabi_divlli",
540 "__moddi3", "__mspabi_remlli",
541 "__mspabi_srall",
542 "__mspabi_srlll",
543 "__mspabi_sllll",
544 "__adddf3", "__mspabi_addd",
545 "__subdf3", "__mspabi_subd",
546 "__muldf3", "__mspabi_mpyd",
547 "__divdf3", "__mspabi_divd",
548 "__mspabi_cmpd",
549 NULL
550};
551
552/* TRUE if the function passed is a "speical" function. Special
553 functions pass two DImode parameters in registers. */
554static bool
555msp430_special_register_convention_p (const char *name)
556{
557 int i;
558
559 for (i = 0; special_convention_function_names [i]; i++)
560 if (! strcmp (name, special_convention_function_names [i]))
561 return true;
562
563 return false;
564}
565
566#undef TARGET_FUNCTION_VALUE_REGNO_P
567#define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
568
569bool
570msp430_function_value_regno_p (unsigned int regno)
571{
572 return regno == 12;
573}
574
575
576#undef TARGET_FUNCTION_VALUE
577#define TARGET_FUNCTION_VALUE msp430_function_value
578
579rtx
580msp430_function_value (const_tree ret_type,
581 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
582 bool outgoing ATTRIBUTE_UNUSED)
583{
584 return gen_rtx_REG (TYPE_MODE (ret_type), 12);
585}
586
587#undef TARGET_LIBCALL_VALUE
588#define TARGET_LIBCALL_VALUE msp430_libcall_value
589
590rtx
3754d046 591msp430_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
e4a25868 592{
593 return gen_rtx_REG (mode, 12);
594}
595
596/* Implements INIT_CUMULATIVE_ARGS. */
597void
598msp430_init_cumulative_args (CUMULATIVE_ARGS *ca,
599 tree fntype ATTRIBUTE_UNUSED,
600 rtx libname ATTRIBUTE_UNUSED,
601 tree fndecl ATTRIBUTE_UNUSED,
602 int n_named_args ATTRIBUTE_UNUSED)
603{
604 const char *fname;
605 memset (ca, 0, sizeof(*ca));
606
607 ca->can_split = 1;
608
609 if (fndecl)
610 fname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
611 else if (libname)
612 fname = XSTR (libname, 0);
613 else
614 fname = NULL;
615
616 if (fname && msp430_special_register_convention_p (fname))
617 ca->special_p = 1;
618}
619
620/* Helper function for argument passing; this function is the common
621 code that determines where an argument will be passed. */
622static void
623msp430_evaluate_arg (cumulative_args_t cap,
3754d046 624 machine_mode mode,
e4a25868 625 const_tree type ATTRIBUTE_UNUSED,
626 bool named)
627{
628 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
629 int nregs = GET_MODE_SIZE (mode);
630 int i;
631
632 ca->reg_count = 0;
633 ca->mem_count = 0;
634
635 if (!named)
636 return;
637
638 if (mode == PSImode)
639 nregs = 1;
640 else
641 nregs = (nregs + 1) / 2;
642
643 if (ca->special_p)
644 {
645 /* Function is passed two DImode operands, in R8:R11 and
646 R12:15. */
647 ca->start_reg = 8;
648 ca->reg_count = 4;
649 return;
650 }
651
652 switch (nregs)
653 {
654 case 1:
655 for (i = 0; i < 4; i++)
656 if (! ca->reg_used [i])
657 {
658 ca->reg_count = 1;
659 ca->start_reg = CA_FIRST_REG + i;
660 return;
661 }
662 break;
663 case 2:
664 for (i = 0; i < 3; i++)
665 if (! ca->reg_used [i] && ! ca->reg_used [i + 1])
666 {
667 ca->reg_count = 2;
668 ca->start_reg = CA_FIRST_REG + i;
669 return;
670 }
671 if (! ca->reg_used [3] && ca->can_split)
672 {
673 ca->reg_count = 1;
674 ca->mem_count = 2;
675 ca->start_reg = CA_FIRST_REG + 3;
676 return;
677 }
678 break;
679 case 3:
680 case 4:
681 ca->can_split = 0;
682 if (! ca->reg_used [0]
683 && ! ca->reg_used [1]
684 && ! ca->reg_used [2]
685 && ! ca->reg_used [3])
686 {
687 ca->reg_count = 4;
688 ca->start_reg = CA_FIRST_REG;
689 return;
690 }
691 break;
692 }
693}
694
695#undef TARGET_PROMOTE_PROTOTYPES
696#define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
697
698bool
699msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED)
700{
701 return false;
702}
703
704#undef TARGET_FUNCTION_ARG
705#define TARGET_FUNCTION_ARG msp430_function_arg
706
707rtx
708msp430_function_arg (cumulative_args_t cap,
3754d046 709 machine_mode mode,
e4a25868 710 const_tree type,
711 bool named)
712{
713 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
714
715 msp430_evaluate_arg (cap, mode, type, named);
716
717 if (ca->reg_count)
718 return gen_rtx_REG (mode, ca->start_reg);
719
720 return 0;
721}
722
723#undef TARGET_ARG_PARTIAL_BYTES
724#define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
725
726int
727msp430_arg_partial_bytes (cumulative_args_t cap,
3754d046 728 machine_mode mode,
e4a25868 729 tree type,
730 bool named)
731{
732 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
733
734 msp430_evaluate_arg (cap, mode, type, named);
735
736 if (ca->reg_count && ca->mem_count)
737 return ca->reg_count * UNITS_PER_WORD;
738
739 return 0;
740}
741
742#undef TARGET_PASS_BY_REFERENCE
743#define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
744
745static bool
746msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED,
3754d046 747 machine_mode mode,
e4a25868 748 const_tree type,
749 bool named ATTRIBUTE_UNUSED)
750{
751 return (mode == BLKmode
752 || (type && TREE_CODE (type) == RECORD_TYPE)
753 || (type && TREE_CODE (type) == UNION_TYPE));
754}
755
756#undef TARGET_CALLEE_COPIES
757#define TARGET_CALLEE_COPIES msp430_callee_copies
758
759static bool
760msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED,
3754d046 761 machine_mode mode ATTRIBUTE_UNUSED,
e4a25868 762 const_tree type ATTRIBUTE_UNUSED,
763 bool named ATTRIBUTE_UNUSED)
764{
765 return true;
766}
767
768#undef TARGET_FUNCTION_ARG_ADVANCE
769#define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
770
771void
772msp430_function_arg_advance (cumulative_args_t cap,
3754d046 773 machine_mode mode,
e4a25868 774 const_tree type,
775 bool named)
776{
777 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
778 int i;
779
780 msp430_evaluate_arg (cap, mode, type, named);
781
782 if (ca->start_reg >= CA_FIRST_REG)
783 for (i = 0; i < ca->reg_count; i ++)
784 ca->reg_used [i + ca->start_reg - CA_FIRST_REG] = 1;
785
786 ca->special_p = 0;
787}
788
789#undef TARGET_FUNCTION_ARG_BOUNDARY
790#define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
791
792static unsigned int
3754d046 793msp430_function_arg_boundary (machine_mode mode, const_tree type)
e4a25868 794{
795 if (mode == BLKmode
796 && int_size_in_bytes (type) > 1)
797 return 16;
798 if (GET_MODE_BITSIZE (mode) > 8)
799 return 16;
800 return 8;
801}
802
803#undef TARGET_RETURN_IN_MEMORY
804#define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
805
806static bool
807msp430_return_in_memory (const_tree ret_type, const_tree fntype ATTRIBUTE_UNUSED)
808{
3754d046 809 machine_mode mode = TYPE_MODE (ret_type);
e4a25868 810
811 if (mode == BLKmode
812 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == RECORD_TYPE)
813 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == UNION_TYPE))
814 return true;
815
816 if (GET_MODE_SIZE (mode) > 8)
817 return true;
818
819 return false;
820}
821
822#undef TARGET_GET_RAW_ARG_MODE
823#define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
824
d2401312 825static fixed_size_mode
e4a25868 826msp430_get_raw_arg_mode (int regno)
827{
d2401312 828 return as_a <fixed_size_mode> (regno == ARG_POINTER_REGNUM
829 ? VOIDmode : Pmode);
e4a25868 830}
831
832#undef TARGET_GET_RAW_RESULT_MODE
833#define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
834
d2401312 835static fixed_size_mode
e4a25868 836msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED)
837{
838 return Pmode;
839}
58f45145 840
841#undef TARGET_GIMPLIFY_VA_ARG_EXPR
842#define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
843
844#include "gimplify.h"
58f45145 845
846static tree
847msp430_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
848 gimple_seq *post_p)
849{
850 tree addr, t, type_size, rounded_size, valist_tmp;
851 unsigned HOST_WIDE_INT align, boundary;
852 bool indirect;
853
854 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
855 if (indirect)
856 type = build_pointer_type (type);
857
858 align = PARM_BOUNDARY / BITS_PER_UNIT;
859 boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
860
861 /* When we align parameter on stack for caller, if the parameter
862 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
863 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
864 here with caller. */
865 if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
866 boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
867
868 boundary /= BITS_PER_UNIT;
869
870 /* Hoist the valist value into a temporary for the moment. */
871 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
872
873 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
874 requires greater alignment, we must perform dynamic alignment. */
875 if (boundary > align
876 && !integer_zerop (TYPE_SIZE (type)))
877 {
878 /* FIXME: This is where this function diverts from targhooks.c:
879 std_gimplify_va_arg_expr(). It works, but I do not know why... */
880 if (! POINTER_TYPE_P (type))
881 {
882 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
883 fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
884 gimplify_and_add (t, pre_p);
885
886 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
887 fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
888 valist_tmp,
889 build_int_cst (TREE_TYPE (valist), -boundary)));
890 gimplify_and_add (t, pre_p);
891 }
892 }
893 else
894 boundary = align;
895
896 /* If the actual alignment is less than the alignment of the type,
897 adjust the type accordingly so that we don't assume strict alignment
898 when dereferencing the pointer. */
899 boundary *= BITS_PER_UNIT;
900 if (boundary < TYPE_ALIGN (type))
901 {
902 type = build_variant_type_copy (type);
5d4b30ea 903 SET_TYPE_ALIGN (type, boundary);
58f45145 904 }
905
906 /* Compute the rounded size of the type. */
907 type_size = size_in_bytes (type);
908 rounded_size = round_up (type_size, align);
909
910 /* Reduce rounded_size so it's sharable with the postqueue. */
911 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
912
913 /* Get AP. */
914 addr = valist_tmp;
915
916 /* Compute new value for AP. */
917 t = fold_build_pointer_plus (valist_tmp, rounded_size);
918 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
919 gimplify_and_add (t, pre_p);
920
921 addr = fold_convert (build_pointer_type (type), addr);
922
923 if (indirect)
924 addr = build_va_arg_indirect_ref (addr);
925
926 addr = build_va_arg_indirect_ref (addr);
927
928 return addr;
929}
e4a25868 930\f
e46fbef5 931#undef TARGET_LRA_P
932#define TARGET_LRA_P hook_bool_void_false
933
e4a25868 934/* Addressing Modes */
935
936#undef TARGET_LEGITIMATE_ADDRESS_P
937#define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
938
939static bool
940reg_ok_for_addr (rtx r, bool strict)
941{
942 int rn = REGNO (r);
943
944 if (strict && rn >= FIRST_PSEUDO_REGISTER)
945 rn = reg_renumber [rn];
946 if (strict && 0 <= rn && rn < FIRST_PSEUDO_REGISTER)
947 return true;
948 if (!strict)
949 return true;
950 return false;
951}
952
953bool
3754d046 954msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
e4a25868 955 rtx x ATTRIBUTE_UNUSED,
956 bool strict ATTRIBUTE_UNUSED)
957{
958 switch (GET_CODE (x))
959 {
960 case MEM:
961 return false;
962
963 case PLUS:
964 if (REG_P (XEXP (x, 0)))
965 {
966 if (GET_MODE (x) != GET_MODE (XEXP (x, 0)))
967 return false;
968 if (!reg_ok_for_addr (XEXP (x, 0), strict))
969 return false;
970 switch (GET_CODE (XEXP (x, 1)))
971 {
972 case CONST:
973 case SYMBOL_REF:
974 case CONST_INT:
975 return true;
976 default:
977 return false;
978 }
979 }
980 return false;
981
982 case REG:
983 if (!reg_ok_for_addr (x, strict))
984 return false;
740d7b0c 985 /* FALLTHRU */
e4a25868 986 case CONST:
987 case SYMBOL_REF:
988 case CONST_INT:
989 return true;
990
991 default:
992 return false;
993 }
994}
995
f6bba390 996#undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
997#define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
998
999bool
3754d046 1000msp430_addr_space_legitimate_address_p (machine_mode mode,
f6bba390 1001 rtx x,
1002 bool strict,
1003 addr_space_t as ATTRIBUTE_UNUSED)
1004{
1005 return msp430_legitimate_address_p (mode, x, strict);
1006}
1007
1008#undef TARGET_ASM_INTEGER
1009#define TARGET_ASM_INTEGER msp430_asm_integer
1010static bool
1011msp430_asm_integer (rtx x, unsigned int size, int aligned_p)
1012{
1013 int c = GET_CODE (x);
1014
1015 if (size == 3 && GET_MODE (x) == PSImode)
1016 size = 4;
1017
1018 switch (size)
1019 {
1020 case 4:
9f961757 1021 if (c == SYMBOL_REF || c == CONST || c == LABEL_REF || c == CONST_INT
1022 || c == PLUS || c == MINUS)
f6bba390 1023 {
1024 fprintf (asm_out_file, "\t.long\t");
1025 output_addr_const (asm_out_file, x);
1026 fputc ('\n', asm_out_file);
1027 return true;
1028 }
1029 break;
1030 }
1031 return default_assemble_integer (x, size, aligned_p);
1032}
1033
1034#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
1035#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra
1036static bool
db606b33 1037msp430_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED, rtx x)
f6bba390 1038{
1039 debug_rtx(x);
1040 return false;
1041}
1042
e4a25868 1043#undef TARGET_LEGITIMATE_CONSTANT_P
1044#define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
1045
1046static bool
3754d046 1047msp430_legitimate_constant (machine_mode mode, rtx x)
e4a25868 1048{
1049 return ! CONST_INT_P (x)
1050 || mode != PSImode
1051 /* GCC does not know the width of the PSImode, so make
1052 sure that it does not try to use a constant value that
1053 is out of range. */
457454ad 1054 || (INTVAL (x) < (1 << 20) && INTVAL (x) >= (HOST_WIDE_INT)(HOST_WIDE_INT_M1U << 20));
e4a25868 1055}
1056
1057\f
1058#undef TARGET_RTX_COSTS
1059#define TARGET_RTX_COSTS msp430_rtx_costs
1060
5ae4887d 1061static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED,
1062 machine_mode mode,
1063 int outer_code ATTRIBUTE_UNUSED,
1064 int opno ATTRIBUTE_UNUSED,
1065 int * total,
1066 bool speed ATTRIBUTE_UNUSED)
e4a25868 1067{
5ae4887d 1068 int code = GET_CODE (x);
1069
e4a25868 1070 switch (code)
1071 {
1072 case SIGN_EXTEND:
5ae4887d 1073 if (mode == SImode && outer_code == SET)
e4a25868 1074 {
1075 *total = COSTS_N_INSNS (4);
1076 return true;
1077 }
1078 break;
1079 case ASHIFT:
1080 case ASHIFTRT:
1081 case LSHIFTRT:
1082 if (!msp430x)
1083 {
1084 *total = COSTS_N_INSNS (100);
1085 return true;
1086 }
1087 break;
1088 }
1089 return false;
1090}
1091\f
1092/* Function Entry and Exit */
1093
1094/* The MSP430 call frame looks like this:
1095
1096 <higher addresses>
1097 +--------------------+
1098 | |
1099 | Stack Arguments |
1100 | |
1101 +--------------------+ <-- "arg pointer"
1102 | |
1103 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
1104 | |
62b2ccbe 1105 +--------------------+
1106 | SR if this func has|
1107 | been called via an |
1108 | interrupt. |
e4a25868 1109 +--------------------+ <-- SP before prologue, also AP
1110 | |
1111 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
1112 | |
1113 +--------------------+ <-- "frame pointer"
1114 | |
1115 | Locals |
1116 | |
1117 +--------------------+
1118 | |
1119 | Outgoing Args |
1120 | |
1121 +--------------------+ <-- SP during function
1122 <lower addresses>
1123
1124*/
1125
1126/* We use this to wrap all emitted insns in the prologue, so they get
1127 the "frame-related" (/f) flag set. */
1128static rtx
1129F (rtx x)
1130{
1131 RTX_FRAME_RELATED_P (x) = 1;
1132 return x;
1133}
1134
1135/* This is the one spot that decides if a register is to be saved and
1136 restored in the prologue/epilogue. */
1137static bool
1138msp430_preserve_reg_p (int regno)
1139{
1140 /* PC, SP, SR, and the constant generator. */
1141 if (regno <= 3)
1142 return false;
1143
1144 /* FIXME: add interrupt, EH, etc. */
1145 if (crtl->calls_eh_return)
1146 return true;
1147
1148 /* Shouldn't be more than the above, but just in case... */
1149 if (fixed_regs [regno])
1150 return false;
1151
34c27987 1152 /* For interrupt functions we must save and restore the used regs that
1153 would normally be caller-saved (R11->R15). */
1154 if (msp430_is_interrupt_func () && regno >= 11 && regno <= 15)
1155 {
1156 if (crtl->is_leaf && df_regs_ever_live_p (regno))
1157 /* If the interrupt func is a leaf then we only need to restore the
1158 caller-saved regs that are used. */
1159 return true;
1160 else if (!crtl->is_leaf)
1161 /* If the interrupt function is not a leaf we must save all
1162 caller-saved regs in case the callee modifies them. */
1163 return true;
1164 }
62b2ccbe 1165
e4a25868 1166 if (!call_used_regs [regno]
1167 && df_regs_ever_live_p (regno))
1168 return true;
1169
1170 return false;
1171}
1172
1173/* Compute all the frame-related fields in our machine_function
1174 structure. */
1175static void
1176msp430_compute_frame_info (void)
1177{
1178 int i;
1179
1180 cfun->machine->computed = 1;
1181 cfun->machine->framesize_regs = 0;
1182 cfun->machine->framesize_locals = get_frame_size ();
1183 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
1184
62b2ccbe 1185 for (i = 0; i < ARG_POINTER_REGNUM; i ++)
e4a25868 1186 if (msp430_preserve_reg_p (i))
1187 {
1188 cfun->machine->need_to_save [i] = 1;
1189 cfun->machine->framesize_regs += (TARGET_LARGE ? 4 : 2);
1190 }
1191 else
1192 cfun->machine->need_to_save [i] = 0;
1193
1194 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
1195 cfun->machine->framesize_locals ++;
1196
1197 cfun->machine->framesize = (cfun->machine->framesize_regs
1198 + cfun->machine->framesize_locals
1199 + cfun->machine->framesize_outgoing);
1200}
1201
ab9c90cd 1202/* Attribute Handling. */
1203
1204const char * const ATTR_INTR = "interrupt";
1205const char * const ATTR_WAKEUP = "wakeup";
1206const char * const ATTR_NAKED = "naked";
1207const char * const ATTR_REENT = "reentrant";
1208const char * const ATTR_CRIT = "critical";
1209const char * const ATTR_LOWER = "lower";
1210const char * const ATTR_UPPER = "upper";
1211const char * const ATTR_EITHER = "either";
4f745ee2 1212const char * const ATTR_NOINIT = "noinit";
1213const char * const ATTR_PERSIST = "persistent";
ab9c90cd 1214
62b2ccbe 1215static inline bool
ab9c90cd 1216has_attr (const char * attr, tree decl)
1217{
1218 if (decl == NULL_TREE)
1219 return false;
1220 return lookup_attribute (attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
1221}
1222
1223static bool
1224is_interrupt_func (tree decl = current_function_decl)
62b2ccbe 1225{
ab9c90cd 1226 return has_attr (ATTR_INTR, decl);
62b2ccbe 1227}
1228
1229/* Returns true if the current function has the "interrupt" attribute. */
1230
1231bool
1232msp430_is_interrupt_func (void)
1233{
ab9c90cd 1234 return is_interrupt_func (current_function_decl);
62b2ccbe 1235}
1236
0a9aab6d 1237static bool
ab9c90cd 1238is_wakeup_func (tree decl = current_function_decl)
0a9aab6d 1239{
ab9c90cd 1240 return is_interrupt_func (decl) && has_attr (ATTR_WAKEUP, decl);
0a9aab6d 1241}
1242
62b2ccbe 1243static inline bool
ab9c90cd 1244is_naked_func (tree decl = current_function_decl)
62b2ccbe 1245{
ab9c90cd 1246 return has_attr (ATTR_NAKED, decl);
62b2ccbe 1247}
1248
1249static inline bool
ab9c90cd 1250is_reentrant_func (tree decl = current_function_decl)
62b2ccbe 1251{
ab9c90cd 1252 return has_attr (ATTR_REENT, decl);
62b2ccbe 1253}
1254
1255static inline bool
ab9c90cd 1256is_critical_func (tree decl = current_function_decl)
1257{
1258 return has_attr (ATTR_CRIT, decl);
1259}
1260
44775fc0 1261static bool
1262has_section_name (const char * name, tree decl = current_function_decl)
1263{
1264 if (decl == NULL_TREE)
1265 return false;
1266 return (DECL_SECTION_NAME (decl)
1267 && (strcmp (name, DECL_SECTION_NAME (decl)) == 0));
1268}
1269
ab9c90cd 1270#undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
1271#define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS msp430_allocate_stack_slots_for_args
1272
1273static bool
1274msp430_allocate_stack_slots_for_args (void)
62b2ccbe 1275{
ab9c90cd 1276 /* Naked functions should not allocate stack slots for arguments. */
1277 return ! is_naked_func ();
62b2ccbe 1278}
1279
9a7154f0 1280#undef TARGET_WARN_FUNC_RETURN
1281#define TARGET_WARN_FUNC_RETURN msp430_warn_func_return
1282
1283static bool
1284msp430_warn_func_return (tree decl)
1285{
1286 /* Naked functions are implemented entirely in assembly, including the
1287 return sequence, so suppress warnings about this. */
1288 return !is_naked_func (decl);
1289}
1290
ab9c90cd 1291/* Verify MSP430 specific attributes. */
1292#define TREE_NAME_EQ(NAME, STR) (strcmp (IDENTIFIER_POINTER (NAME), (STR)) == 0)
1293
1294static tree
1295msp430_attr (tree * node,
1296 tree name,
1297 tree args,
1298 int flags ATTRIBUTE_UNUSED,
1299 bool * no_add_attrs)
1300{
1301 gcc_assert (DECL_P (* node));
1302
bef3ffe8 1303 /* Only the interrupt attribute takes an argument. */
ab9c90cd 1304 if (args != NULL)
1305 {
ab9c90cd 1306 tree value = TREE_VALUE (args);
1307
1308 switch (TREE_CODE (value))
1309 {
1310 case STRING_CST:
1311 if ( strcmp (TREE_STRING_POINTER (value), "reset")
1312 && strcmp (TREE_STRING_POINTER (value), "nmi")
1313 && strcmp (TREE_STRING_POINTER (value), "watchdog"))
1314 /* Allow the attribute to be added - the linker script
1315 being used may still recognise this name. */
1316 warning (OPT_Wattributes,
d0abd9e0 1317 "unrecognized interrupt vector argument of %qE attribute",
ab9c90cd 1318 name);
1319 break;
1320
1321 case INTEGER_CST:
e3d0f65c 1322 if (wi::gtu_p (wi::to_wide (value), 63))
ab9c90cd 1323 /* Allow the attribute to be added - the linker script
1324 being used may still recognise this value. */
1325 warning (OPT_Wattributes,
1326 "numeric argument of %qE attribute must be in range 0..63",
1327 name);
1328 break;
1329
1330 default:
1331 warning (OPT_Wattributes,
1332 "argument of %qE attribute is not a string constant or number",
1333 name);
1334 *no_add_attrs = true;
1335 break;
1336 }
1337 }
1338
1339 const char * message = NULL;
1340
1341 if (TREE_CODE (* node) != FUNCTION_DECL)
1342 {
1343 message = "%qE attribute only applies to functions";
1344 }
1345 else if (TREE_NAME_EQ (name, ATTR_INTR))
1346 {
1347 if (TREE_CODE (TREE_TYPE (* node)) == FUNCTION_TYPE
1348 && ! VOID_TYPE_P (TREE_TYPE (TREE_TYPE (* node))))
1349 message = "interrupt handlers must be void";
bef3ffe8 1350 else
1351 {
1352 /* Ensure interrupt handlers never get optimised out. */
1353 TREE_USED (* node) = 1;
1354 DECL_PRESERVE_P (* node) = 1;
1355 }
96c8047a 1356 if (is_critical_func (* node))
1357 {
1358 warning (OPT_Wattributes,
1359 "critical attribute has no effect on interrupt functions");
1360 DECL_ATTRIBUTES (*node) = remove_attribute (ATTR_CRIT,
1361 DECL_ATTRIBUTES (* node));
1362 }
ab9c90cd 1363 }
1364 else if (TREE_NAME_EQ (name, ATTR_REENT))
1365 {
1366 if (is_naked_func (* node))
1367 message = "naked functions cannot be reentrant";
1368 else if (is_critical_func (* node))
1369 message = "critical functions cannot be reentrant";
1370 }
1371 else if (TREE_NAME_EQ (name, ATTR_CRIT))
1372 {
1373 if (is_naked_func (* node))
1374 message = "naked functions cannot be critical";
1375 else if (is_reentrant_func (* node))
4f745ee2 1376 message = "reentrant functions cannot be critical";
96c8047a 1377 else if (is_interrupt_func ( *node))
1378 message = "critical attribute has no effect on interrupt functions";
ab9c90cd 1379 }
1380 else if (TREE_NAME_EQ (name, ATTR_NAKED))
1381 {
1382 if (is_critical_func (* node))
1383 message = "critical functions cannot be naked";
1384 else if (is_reentrant_func (* node))
1385 message = "reentrant functions cannot be naked";
1386 }
1387
1388 if (message)
1389 {
1390 warning (OPT_Wattributes, message, name);
1391 * no_add_attrs = true;
1392 }
1393
1394 return NULL_TREE;
1395}
1396
1397static tree
1398msp430_section_attr (tree * node,
1399 tree name,
1400 tree args,
1401 int flags ATTRIBUTE_UNUSED,
1402 bool * no_add_attrs ATTRIBUTE_UNUSED)
1403{
1404 gcc_assert (DECL_P (* node));
1405 gcc_assert (args == NULL);
1406
1407 const char * message = NULL;
1408
1409 if (TREE_NAME_EQ (name, ATTR_UPPER))
1410 {
1411 if (has_attr (ATTR_LOWER, * node))
1412 message = "already marked with 'lower' attribute";
1413 else if (has_attr (ATTR_EITHER, * node))
1414 message = "already marked with 'either' attribute";
1415 else if (! msp430x)
1416 message = "upper attribute needs a 430X cpu";
1417 }
1418 else if (TREE_NAME_EQ (name, ATTR_LOWER))
1419 {
1420 if (has_attr (ATTR_UPPER, * node))
1421 message = "already marked with 'upper' attribute";
1422 else if (has_attr (ATTR_EITHER, * node))
1423 message = "already marked with 'either' attribute";
1424 }
1425 else
1426 {
1427 gcc_assert (TREE_NAME_EQ (name, ATTR_EITHER));
1428
1429 if (has_attr (ATTR_LOWER, * node))
1430 message = "already marked with 'lower' attribute";
1431 else if (has_attr (ATTR_UPPER, * node))
1432 message = "already marked with 'upper' attribute";
1433 }
1434
4b12180b 1435 /* It does not make sense to use upper/lower/either attributes without
1436 -mlarge.
1437 Without -mlarge, "lower" is the default and only region, so is redundant.
1438 Without -mlarge, "upper" will (and "either" might) place code/data in the
1439 upper region, which for data could result in relocation overflows, and for
1440 code could result in stack mismanagement and incorrect call/return
1441 instructions. */
1442 if (!TARGET_LARGE)
1443 message = G_("%qE attribute ignored. large memory model (%<-mlarge%>) "
1444 "is required");
1445
ab9c90cd 1446 if (message)
1447 {
1448 warning (OPT_Wattributes, message, name);
1449 * no_add_attrs = true;
1450 }
1451
1452 return NULL_TREE;
1453}
1454
4f745ee2 1455static tree
1456msp430_data_attr (tree * node,
1457 tree name,
1458 tree args,
1459 int flags ATTRIBUTE_UNUSED,
1460 bool * no_add_attrs ATTRIBUTE_UNUSED)
1461{
1462 const char * message = NULL;
1463
1464 gcc_assert (DECL_P (* node));
1465 gcc_assert (args == NULL);
1466
1467 if (TREE_CODE (* node) != VAR_DECL)
f6e4a711 1468 message = G_("%qE attribute only applies to variables");
1469
1470 /* Check that it's possible for the variable to have a section. */
1471 if ((TREE_STATIC (* node) || DECL_EXTERNAL (* node) || in_lto_p)
1472 && DECL_SECTION_NAME (* node))
1473 message = G_("%qE attribute cannot be applied to variables with specific sections");
1474
1475 if (!message && TREE_NAME_EQ (name, ATTR_PERSIST) && !TREE_STATIC (* node)
1476 && !TREE_PUBLIC (* node) && !DECL_EXTERNAL (* node))
1477 message = G_("%qE attribute has no effect on automatic variables");
1478
1479 /* It's not clear if there is anything that can be set here to prevent the
1480 front end placing the variable before the back end can handle it, in a
1481 similar way to how DECL_COMMON is used below.
1482 So just place the variable in the .persistent section now. */
1483 if ((TREE_STATIC (* node) || DECL_EXTERNAL (* node) || in_lto_p)
1484 && TREE_NAME_EQ (name, ATTR_PERSIST))
1485 set_decl_section_name (* node, ".persistent");
4f745ee2 1486
1487 /* If this var is thought to be common, then change this. Common variables
1488 are assigned to sections before the backend has a chance to process them. */
1489 if (DECL_COMMON (* node))
1490 DECL_COMMON (* node) = 0;
1491
1492 if (message)
1493 {
1494 warning (OPT_Wattributes, message, name);
1495 * no_add_attrs = true;
1496 }
1497
1498 return NULL_TREE;
1499}
1500
1501
ab9c90cd 1502#undef TARGET_ATTRIBUTE_TABLE
1503#define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
1504
1505/* Table of MSP430-specific attributes. */
1506const struct attribute_spec msp430_attribute_table[] =
1507{
672bc44d 1508 /* Name min_num_args type_req, handler
1509 max_num_args, fn_type_req exclude
1510 decl_req affects_type_identity. */
1511 { ATTR_INTR, 0, 1, true, false, false, false, msp430_attr, NULL },
1512 { ATTR_NAKED, 0, 0, true, false, false, false, msp430_attr, NULL },
1513 { ATTR_REENT, 0, 0, true, false, false, false, msp430_attr, NULL },
1514 { ATTR_CRIT, 0, 0, true, false, false, false, msp430_attr, NULL },
1515 { ATTR_WAKEUP, 0, 0, true, false, false, false, msp430_attr, NULL },
1516
1517 { ATTR_LOWER, 0, 0, true, false, false, false, msp430_section_attr,
dab0e385 1518 NULL },
672bc44d 1519 { ATTR_UPPER, 0, 0, true, false, false, false, msp430_section_attr,
dab0e385 1520 NULL },
672bc44d 1521 { ATTR_EITHER, 0, 0, true, false, false, false, msp430_section_attr,
dab0e385 1522 NULL },
1523
672bc44d 1524 { ATTR_PERSIST, 0, 0, true, false, false, false, msp430_data_attr,
dab0e385 1525 NULL },
1526
672bc44d 1527 { NULL, 0, 0, false, false, false, false, NULL, NULL }
ab9c90cd 1528};
1529
e4a25868 1530#undef TARGET_ASM_FUNCTION_PROLOGUE
1531#define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
1532
1533static void
718e6d56 1534msp430_start_function (FILE *outfile)
e4a25868 1535{
1536 int r, n;
1537
1538 fprintf (outfile, "; start of function\n");
62b2ccbe 1539
1540 if (DECL_ATTRIBUTES (current_function_decl) != NULL_TREE)
1541 {
1542 fprintf (outfile, "; attributes: ");
1543 if (is_naked_func ())
1544 fprintf (outfile, "naked ");
1545 if (msp430_is_interrupt_func ())
1546 fprintf (outfile, "interrupt ");
1547 if (is_reentrant_func ())
1548 fprintf (outfile, "reentrant ");
1549 if (is_critical_func ())
1550 fprintf (outfile, "critical ");
0a9aab6d 1551 if (is_wakeup_func ())
1552 fprintf (outfile, "wakeup ");
62b2ccbe 1553 fprintf (outfile, "\n");
1554 }
1555
e4a25868 1556 fprintf (outfile, "; framesize_regs: %d\n", cfun->machine->framesize_regs);
1557 fprintf (outfile, "; framesize_locals: %d\n", cfun->machine->framesize_locals);
1558 fprintf (outfile, "; framesize_outgoing: %d\n", cfun->machine->framesize_outgoing);
1559 fprintf (outfile, "; framesize: %d\n", cfun->machine->framesize);
1560 fprintf (outfile, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM));
1561 fprintf (outfile, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM));
1562
1563 n = 0;
1564 fprintf (outfile, "; saved regs:");
62b2ccbe 1565 for (r = 0; r < ARG_POINTER_REGNUM; r++)
e4a25868 1566 if (cfun->machine->need_to_save [r])
1567 {
1568 fprintf (outfile, " %s", reg_names [r]);
1569 n = 1;
1570 }
1571 if (n == 0)
1572 fprintf (outfile, "(none)");
1573 fprintf (outfile, "\n");
1574}
1575
1576/* Common code to change the stack pointer. */
1577static void
1578increment_stack (HOST_WIDE_INT amount)
1579{
1580 rtx inc;
1581 rtx sp = stack_pointer_rtx;
1582
1583 if (amount == 0)
1584 return;
1585
1586 if (amount < 0)
1587 {
1588 inc = GEN_INT (- amount);
1589 if (TARGET_LARGE)
1590 F (emit_insn (gen_subpsi3 (sp, sp, inc)));
1591 else
1592 F (emit_insn (gen_subhi3 (sp, sp, inc)));
1593 }
1594 else
1595 {
1596 inc = GEN_INT (amount);
1597 if (TARGET_LARGE)
1598 emit_insn (gen_addpsi3 (sp, sp, inc));
1599 else
1600 emit_insn (gen_addhi3 (sp, sp, inc));
1601 }
1602}
1603
62b2ccbe 1604void
1605msp430_start_function (FILE *file, const char *name, tree decl)
1606{
1607 tree int_attr;
1608
1609 int_attr = lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl));
1610 if (int_attr != NULL_TREE)
1611 {
1612 tree intr_vector = TREE_VALUE (int_attr);
1613
1614 if (intr_vector != NULL_TREE)
1615 {
1616 char buf[101];
1617
1098c313 1618 /* Interrupt vector sections should be unique, but use of weak
1619 functions implies multiple definitions. */
1620 if (DECL_WEAK (decl))
1621 {
1622 error ("argument to interrupt attribute is unsupported for weak functions");
1623 }
1624
62b2ccbe 1625 intr_vector = TREE_VALUE (intr_vector);
1626
1627 /* The interrupt attribute has a vector value. Turn this into a
1628 section name, switch to that section and put the address of
1629 the current function into that vector slot. Note msp430_attr()
1630 has already verified the vector name for us. */
1631 if (TREE_CODE (intr_vector) == STRING_CST)
1632 sprintf (buf, "__interrupt_vector_%.80s",
1633 TREE_STRING_POINTER (intr_vector));
1634 else /* TREE_CODE (intr_vector) == INTEGER_CST */
1635 sprintf (buf, "__interrupt_vector_%u",
f9ae6f95 1636 (unsigned int) TREE_INT_CST_LOW (intr_vector));
62b2ccbe 1637
1638 switch_to_section (get_section (buf, SECTION_CODE, decl));
1639 fputs ("\t.word\t", file);
1640 assemble_name (file, name);
1641 fputc ('\n', file);
1642 fputc ('\t', file);
1643 }
1644 }
1645
1646 switch_to_section (function_section (decl));
2cc8e106 1647 ASM_OUTPUT_TYPE_DIRECTIVE(file, name, "function");
62b2ccbe 1648 ASM_OUTPUT_FUNCTION_LABEL (file, name, decl);
1649}
1650
ab9c90cd 1651static const char * const lower_prefix = ".lower";
1652static const char * const upper_prefix = ".upper";
1653static const char * const either_prefix = ".either";
1654
1655/* Generate a prefix for a section name, based upon
1656 the region into which the object should be placed. */
1657
1658static const char *
1659gen_prefix (tree decl)
1660{
1661 if (DECL_ONE_ONLY (decl))
1662 return NULL;
1663
1664 /* If the user has specified a particular section then do not use any prefix. */
1665 if (has_attr ("section", decl))
1666 return NULL;
1667
44775fc0 1668 /* If the function has been put in the .lowtext section (because it is an
1669 interrupt handler, and the large memory model is used), then do not add
1670 any prefixes. */
1671 if (has_section_name (".lowtext", decl))
1672 return NULL;
1673
ab9c90cd 1674 /* If the object has __attribute__((lower)) then use the ".lower." prefix. */
1675 if (has_attr (ATTR_LOWER, decl))
1676 return lower_prefix;
1677
1678 /* If we are compiling for the MSP430 then we do not support the upper region. */
1679 if (! msp430x)
1680 return NULL;
1681
1682 if (has_attr (ATTR_UPPER, decl))
1683 return upper_prefix;
1684
1685 if (has_attr (ATTR_EITHER, decl))
1686 return either_prefix;
1687
1688 if (TREE_CODE (decl) == FUNCTION_DECL)
1689 {
bdc549ca 1690 if (msp430_code_region == MSP430_REGION_LOWER)
ab9c90cd 1691 return lower_prefix;
1692
bdc549ca 1693 if (msp430_code_region == MSP430_REGION_UPPER)
ab9c90cd 1694 return upper_prefix;
1695
bdc549ca 1696 if (msp430_code_region == MSP430_REGION_EITHER)
ab9c90cd 1697 return either_prefix;
1698 }
1699 else
1700 {
bdc549ca 1701 if (msp430_data_region == MSP430_REGION_LOWER)
ab9c90cd 1702 return lower_prefix;
1703
bdc549ca 1704 if (msp430_data_region == MSP430_REGION_UPPER)
ab9c90cd 1705 return upper_prefix;
1706
bdc549ca 1707 if (msp430_data_region == MSP430_REGION_EITHER)
ab9c90cd 1708 return either_prefix;
1709 }
1710
1711 return NULL;
1712}
1713
4f745ee2 1714static section * noinit_section;
1715static section * persist_section;
1716
1717#undef TARGET_ASM_INIT_SECTIONS
1718#define TARGET_ASM_INIT_SECTIONS msp430_init_sections
1719
1720static void
1721msp430_init_sections (void)
1722{
1723 noinit_section = get_unnamed_section (0, output_section_asm_op, ".section .noinit,\"aw\"");
1724 persist_section = get_unnamed_section (0, output_section_asm_op, ".section .persistent,\"aw\"");
1725}
1726
ab9c90cd 1727#undef TARGET_ASM_SELECT_SECTION
1728#define TARGET_ASM_SELECT_SECTION msp430_select_section
1729
62b2ccbe 1730static section *
ab9c90cd 1731msp430_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
62b2ccbe 1732{
ab9c90cd 1733 gcc_assert (decl != NULL_TREE);
1734
1735 if (TREE_CODE (decl) == STRING_CST
1736 || TREE_CODE (decl) == CONSTRUCTOR
1737 || TREE_CODE (decl) == INTEGER_CST
1738 || TREE_CODE (decl) == VECTOR_CST
1739 || TREE_CODE (decl) == COMPLEX_CST)
1740 return default_select_section (decl, reloc, align);
1741
62b2ccbe 1742 /* In large mode we must make sure that interrupt handlers are put into
1743 low memory as the vector table only accepts 16-bit addresses. */
ab9c90cd 1744 if (TARGET_LARGE && TREE_CODE (decl) == FUNCTION_DECL && is_interrupt_func (decl))
62b2ccbe 1745 return get_section (".lowtext", SECTION_CODE | SECTION_WRITE , decl);
1746
ab9c90cd 1747 const char * prefix = gen_prefix (decl);
1748 if (prefix == NULL)
1749 {
1750 if (TREE_CODE (decl) == FUNCTION_DECL)
1751 return text_section;
d6491b52 1752 /* FIXME: ATTR_NOINIT is handled generically in
1753 default_elf_select_section. */
4f745ee2 1754 else if (has_attr (ATTR_NOINIT, decl))
1755 return noinit_section;
1756 else if (has_attr (ATTR_PERSIST, decl))
1757 return persist_section;
ab9c90cd 1758 else
1759 return default_select_section (decl, reloc, align);
1760 }
1761
1762 const char * sec;
1763 switch (categorize_decl_for_section (decl, reloc))
1764 {
1765 case SECCAT_TEXT: sec = ".text"; break;
1766 case SECCAT_DATA: sec = ".data"; break;
1767 case SECCAT_BSS: sec = ".bss"; break;
1768 case SECCAT_RODATA: sec = ".rodata"; break;
1769
1770 case SECCAT_RODATA_MERGE_STR:
1771 case SECCAT_RODATA_MERGE_STR_INIT:
1772 case SECCAT_RODATA_MERGE_CONST:
1773 case SECCAT_SRODATA:
1774 case SECCAT_DATA_REL:
1775 case SECCAT_DATA_REL_LOCAL:
1776 case SECCAT_DATA_REL_RO:
1777 case SECCAT_DATA_REL_RO_LOCAL:
1778 case SECCAT_SDATA:
1779 case SECCAT_SBSS:
1780 case SECCAT_TDATA:
1781 case SECCAT_TBSS:
1782 return default_select_section (decl, reloc, align);
1783
1784 default:
1785 gcc_unreachable ();
1786 }
1787
1788 const char * dec_name = DECL_SECTION_NAME (decl);
1789 char * name = ACONCAT ((prefix, sec, dec_name, NULL));
1790
1791 return get_named_section (decl, name, 0);
62b2ccbe 1792}
1793
1794#undef TARGET_ASM_FUNCTION_SECTION
1795#define TARGET_ASM_FUNCTION_SECTION msp430_function_section
1796
ab9c90cd 1797static section *
1798msp430_function_section (tree decl, enum node_frequency freq, bool startup, bool exit)
1799{
1800 const char * name;
1801
1802 gcc_assert (DECL_SECTION_NAME (decl) != NULL);
1803 name = DECL_SECTION_NAME (decl);
1804
1805 const char * prefix = gen_prefix (decl);
1806 if (prefix == NULL
1807 || strncmp (name, prefix, strlen (prefix)) == 0)
1808 return default_function_section (decl, freq, startup, exit);
1809
1810 name = ACONCAT ((prefix, name, NULL));
1811 return get_named_section (decl, name, 0);
1812}
1813
1814#undef TARGET_SECTION_TYPE_FLAGS
1815#define TARGET_SECTION_TYPE_FLAGS msp430_section_type_flags
1816
1817unsigned int
1818msp430_section_type_flags (tree decl, const char * name, int reloc)
1819{
1820 if (strncmp (name, lower_prefix, strlen (lower_prefix)) == 0)
1821 name += strlen (lower_prefix);
1822 else if (strncmp (name, upper_prefix, strlen (upper_prefix)) == 0)
1823 name += strlen (upper_prefix);
1824 else if (strncmp (name, either_prefix, strlen (either_prefix)) == 0)
1825 name += strlen (either_prefix);
4f745ee2 1826 else if (strcmp (name, ".noinit") == 0)
1827 return SECTION_WRITE | SECTION_BSS | SECTION_NOTYPE;
02059be0 1828 else if (strcmp (name, ".persistent") == 0)
4f745ee2 1829 return SECTION_WRITE | SECTION_NOTYPE;
1830
ab9c90cd 1831 return default_section_type_flags (decl, name, reloc);
1832}
1833
1834#undef TARGET_ASM_UNIQUE_SECTION
1835#define TARGET_ASM_UNIQUE_SECTION msp430_unique_section
1836
1837static void
1838msp430_unique_section (tree decl, int reloc)
1839{
1840 gcc_assert (decl != NULL_TREE);
1841
1842 /* In large mode we must make sure that interrupt handlers are put into
1843 low memory as the vector table only accepts 16-bit addresses. */
1844 if (TARGET_LARGE && TREE_CODE (decl) == FUNCTION_DECL && is_interrupt_func (decl))
1845 {
1846 set_decl_section_name (decl, ".lowtext");
1847 return;
1848 }
1849
1850 default_unique_section (decl, reloc);
1851
1852 const char * prefix;
1853
1854 if ( TREE_CODE (decl) == STRING_CST
1855 || TREE_CODE (decl) == CONSTRUCTOR
1856 || TREE_CODE (decl) == INTEGER_CST
1857 || TREE_CODE (decl) == VECTOR_CST
1858 || TREE_CODE (decl) == COMPLEX_CST
1859 || (prefix = gen_prefix (decl)) == NULL
1860 )
1861 return;
1862
1863 const char * dec_name = DECL_SECTION_NAME (decl);
1864 char * name = ACONCAT ((prefix, dec_name, NULL));
1865
1866 set_decl_section_name (decl, name);
1867}
1868
1869/* Emit a declaration of a common symbol.
1870 If a data region is in use then put the symbol into the
1871 equivalent .bss section instead. */
1872
1873void
1874msp430_output_aligned_decl_common (FILE * stream,
1875 const tree decl,
1876 const char * name,
1877 unsigned HOST_WIDE_INT size,
1878 unsigned int align)
1879{
bdc549ca 1880 if (msp430_data_region == MSP430_REGION_ANY)
ab9c90cd 1881 {
1882 fprintf (stream, COMMON_ASM_OP);
1883 assemble_name (stream, name);
f03df321 1884 fprintf (stream, "," HOST_WIDE_INT_PRINT_UNSIGNED",%u\n",
ab9c90cd 1885 size, align / BITS_PER_UNIT);
1886 }
1887 else
1888 {
1889 section * sec;
1890
1891 if (decl)
1892 sec = msp430_select_section (decl, 0, align);
1893 else
1894 switch (msp430_data_region)
1895 {
bdc549ca 1896 case MSP430_REGION_UPPER: sec = get_named_section (NULL, ".upper.bss", 0); break;
1897 case MSP430_REGION_LOWER: sec = get_named_section (NULL, ".lower.bss", 0); break;
1898 case MSP430_REGION_EITHER: sec = get_named_section (NULL, ".either.bss", 0); break;
ab9c90cd 1899 default:
1900 gcc_unreachable ();
1901 }
1902 gcc_assert (sec != NULL);
1903
1904 switch_to_section (sec);
1905 ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
1906 targetm.asm_out.globalize_label (stream, name);
1907 ASM_WEAKEN_LABEL (stream, name);
1908 ASM_OUTPUT_LABEL (stream, name);
1909 ASM_OUTPUT_SKIP (stream, size ? size : 1);
1910 }
1911}
1912
1913bool
1914msp430_do_not_relax_short_jumps (void)
1915{
1916 /* When placing code into "either" low or high memory we do not want the linker
1917 to grow the size of sections, which it can do if it is encounters a branch to
1918 a label that is too far away. So we tell the cbranch patterns to avoid using
1919 short jumps when there is a chance that the instructions will end up in a low
1920 section. */
1921 return
bdc549ca 1922 msp430_code_region == MSP430_REGION_EITHER
1923 || msp430_code_region == MSP430_REGION_LOWER
ab9c90cd 1924 || has_attr (ATTR_EITHER, current_function_decl)
1925 || has_attr (ATTR_LOWER, current_function_decl);
1926}
1927
62b2ccbe 1928enum msp430_builtin
1929{
1930 MSP430_BUILTIN_BIC_SR,
1931 MSP430_BUILTIN_BIS_SR,
9f70b545 1932 MSP430_BUILTIN_DELAY_CYCLES,
62b2ccbe 1933 MSP430_BUILTIN_max
1934};
1935
1936static GTY(()) tree msp430_builtins [(int) MSP430_BUILTIN_max];
1937
1938static void
1939msp430_init_builtins (void)
1940{
1941 tree void_ftype_int = build_function_type_list (void_type_node, integer_type_node, NULL);
9f70b545 1942 tree void_ftype_longlong = build_function_type_list (void_type_node, long_long_integer_type_node, NULL);
62b2ccbe 1943
1944 msp430_builtins[MSP430_BUILTIN_BIC_SR] =
1945 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int,
1946 MSP430_BUILTIN_BIC_SR, BUILT_IN_MD, NULL, NULL_TREE);
1947
1948 msp430_builtins[MSP430_BUILTIN_BIS_SR] =
1949 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int,
1950 MSP430_BUILTIN_BIS_SR, BUILT_IN_MD, NULL, NULL_TREE);
9f70b545 1951
1952 msp430_builtins[MSP430_BUILTIN_DELAY_CYCLES] =
1953 add_builtin_function ( "__delay_cycles", void_ftype_longlong,
1954 MSP430_BUILTIN_DELAY_CYCLES, BUILT_IN_MD, NULL, NULL_TREE);
62b2ccbe 1955}
1956
1957static tree
1958msp430_builtin_decl (unsigned code, bool initialize ATTRIBUTE_UNUSED)
1959{
1960 switch (code)
1961 {
1962 case MSP430_BUILTIN_BIC_SR:
1963 case MSP430_BUILTIN_BIS_SR:
9f70b545 1964 case MSP430_BUILTIN_DELAY_CYCLES:
62b2ccbe 1965 return msp430_builtins[code];
1966 default:
1967 return error_mark_node;
1968 }
1969}
1970
9f70b545 1971/* These constants are really register reads, which are faster than
1972 regular constants. */
1973static int
1974cg_magic_constant (HOST_WIDE_INT c)
1975{
1976 switch (c)
1977 {
1978 case 0xffff:
1979 case -1:
1980 case 0:
1981 case 1:
1982 case 2:
1983 case 4:
1984 case 8:
1985 return 1;
1986 default:
1987 return 0;
1988 }
1989}
1990
1991static rtx
1992msp430_expand_delay_cycles (rtx arg)
1993{
1994 HOST_WIDE_INT i, c, n;
1995 /* extra cycles for MSP430X instructions */
1996#define CYCX(M,X) (msp430x ? (X) : (M))
1997
1998 if (GET_CODE (arg) != CONST_INT)
1999 {
2000 error ("__delay_cycles() only takes constant arguments");
2001 return NULL_RTX;
2002 }
2003
2004 c = INTVAL (arg);
2005
2006 if (HOST_BITS_PER_WIDE_INT > 32)
2007 {
2008 if (c < 0)
2009 {
1c62dfe7 2010 error ("__delay_cycles only takes non-negative cycle counts");
9f70b545 2011 return NULL_RTX;
2012 }
2013 }
2014
2015 emit_insn (gen_delay_cycles_start (arg));
2016
2017 /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
2018 if (c > 3 * 0xffff + CYCX (7, 10))
2019 {
2020 n = c;
2021 /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
2022 if (c >= 0x10000 * 7 + CYCX (14, 16))
2023 {
2024 i = 0x10000;
2025 c -= CYCX (14, 16) + 7 * 0x10000;
2026 i += c / 4;
2027 c %= 4;
2028 if ((unsigned long long) i > 0xffffffffULL)
2029 {
1c62dfe7 2030 error ("__delay_cycles is limited to 32-bit loop counts");
9f70b545 2031 return NULL_RTX;
2032 }
2033 }
2034 else
2035 {
2036 i = (c - CYCX (14, 16)) / 7;
2037 c -= CYCX (14, 16) + i * 7;
2038 }
2039
2040 if (cg_magic_constant (i & 0xffff))
2041 c ++;
2042 if (cg_magic_constant ((i >> 16) & 0xffff))
2043 c ++;
2044
2045 if (msp430x)
2046 emit_insn (gen_delay_cycles_32x (GEN_INT (i), GEN_INT (n - c)));
2047 else
2048 emit_insn (gen_delay_cycles_32 (GEN_INT (i), GEN_INT (n - c)));
2049 }
2050
2051 /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
2052 if (c > 12)
2053 {
2054 n = c;
2055 i = (c - CYCX (7, 10)) / 3;
2056 c -= CYCX (7, 10) + i * 3;
2057
2058 if (cg_magic_constant (i))
2059 c ++;
2060
2061 if (msp430x)
2062 emit_insn (gen_delay_cycles_16x (GEN_INT (i), GEN_INT (n - c)));
2063 else
2064 emit_insn (gen_delay_cycles_16 (GEN_INT (i), GEN_INT (n - c)));
2065 }
2066
2067 while (c > 1)
2068 {
2069 emit_insn (gen_delay_cycles_2 ());
2070 c -= 2;
2071 }
2072
2073 if (c)
2074 {
2075 emit_insn (gen_delay_cycles_1 ());
2076 c -= 1;
2077 }
2078
2079 emit_insn (gen_delay_cycles_end (arg));
2080
2081 return NULL_RTX;
2082}
2083
62b2ccbe 2084static rtx
2085msp430_expand_builtin (tree exp,
2086 rtx target ATTRIBUTE_UNUSED,
2087 rtx subtarget ATTRIBUTE_UNUSED,
3754d046 2088 machine_mode mode ATTRIBUTE_UNUSED,
62b2ccbe 2089 int ignore ATTRIBUTE_UNUSED)
2090{
2091 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
d1170f8d 2092 unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
62b2ccbe 2093 rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
2094
9f70b545 2095 if (fcode == MSP430_BUILTIN_DELAY_CYCLES)
2096 return msp430_expand_delay_cycles (arg1);
2097
62b2ccbe 2098 if (! msp430_is_interrupt_func ())
2099 {
2100 error ("MSP430 builtin functions only work inside interrupt handlers");
2101 return NULL_RTX;
2102 }
2103
2104 if (! REG_P (arg1) && ! CONSTANT_P (arg1))
2105 arg1 = force_reg (mode, arg1);
2106
2107 switch (fcode)
2108 {
2109 case MSP430_BUILTIN_BIC_SR: emit_insn (gen_bic_SR (arg1)); break;
2110 case MSP430_BUILTIN_BIS_SR: emit_insn (gen_bis_SR (arg1)); break;
2111 default:
2112 internal_error ("bad builtin code");
2113 break;
2114 }
2115 return NULL_RTX;
2116}
2117
2118#undef TARGET_INIT_BUILTINS
2119#define TARGET_INIT_BUILTINS msp430_init_builtins
2120
2121#undef TARGET_EXPAND_BUILTIN
2122#define TARGET_EXPAND_BUILTIN msp430_expand_builtin
2123
2124#undef TARGET_BUILTIN_DECL
2125#define TARGET_BUILTIN_DECL msp430_builtin_decl
2126
e4a25868 2127void
2128msp430_expand_prologue (void)
2129{
2130 int i, j;
2131 int fs;
2132 /* Always use stack_pointer_rtx instead of calling
2133 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
2134 that there is a single rtx representing the stack pointer,
2135 namely stack_pointer_rtx, and uses == to recognize it. */
2136 rtx sp = stack_pointer_rtx;
2137 rtx p;
2138
62b2ccbe 2139 if (is_naked_func ())
f87a602b 2140 {
2141 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2142 examines the output of the gen_prologue() function. */
2143 emit_insn (gen_rtx_CLOBBER (VOIDmode, GEN_INT (0)));
2144 return;
2145 }
62b2ccbe 2146
e4a25868 2147 emit_insn (gen_prologue_start_marker ());
2148
62b2ccbe 2149 if (is_critical_func ())
2150 {
2151 emit_insn (gen_push_intr_state ());
2152 emit_insn (gen_disable_interrupts ());
2153 }
2154 else if (is_reentrant_func ())
2155 emit_insn (gen_disable_interrupts ());
2156
e4a25868 2157 if (!cfun->machine->computed)
2158 msp430_compute_frame_info ();
2159
2160 if (flag_stack_usage_info)
2161 current_function_static_stack_size = cfun->machine->framesize;
6956ee35 2162
e4a25868 2163 if (crtl->args.pretend_args_size)
2164 {
2165 rtx note;
2166
2167 gcc_assert (crtl->args.pretend_args_size == 2);
6956ee35 2168
e4a25868 2169 p = emit_insn (gen_grow_and_swap ());
2170
2171 /* Document the stack decrement... */
d1f9b275 2172 note = F (gen_rtx_SET (stack_pointer_rtx,
e4a25868 2173 gen_rtx_MINUS (Pmode, stack_pointer_rtx, GEN_INT (2))));
2174 add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
2175
2176 /* ...and the establishment of a new location for the return address. */
d1f9b275 2177 note = F (gen_rtx_SET (gen_rtx_MEM (Pmode,
2178 gen_rtx_PLUS (Pmode,
2179 stack_pointer_rtx,
2180 GEN_INT (-2))),
e4a25868 2181 pc_rtx));
2182 add_reg_note (p, REG_CFA_OFFSET, note);
2183 F (p);
2184 }
2185
2186 for (i = 15; i >= 4; i--)
2187 if (cfun->machine->need_to_save [i])
2188 {
2189 int seq, count;
2190 rtx note;
2191
2192 for (seq = i - 1; seq >= 4 && cfun->machine->need_to_save[seq]; seq --)
2193 ;
2194 count = i - seq;
2195
2196 if (msp430x)
2197 {
2198 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
2199 p = F (emit_insn (gen_pushm (gen_rtx_REG (Pmode, i),
2200 GEN_INT (count))));
2201
2202 note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1));
2203
2204 XVECEXP (note, 0, 0)
d1f9b275 2205 = F (gen_rtx_SET (stack_pointer_rtx,
2206 gen_rtx_PLUS (Pmode,
2207 stack_pointer_rtx,
2208 GEN_INT (count * (TARGET_LARGE ? -4 : -2)))));
e4a25868 2209
2210 /* *sp-- = R[i-j] */
2211 /* sp+N R10
2212 ...
2213 sp R4 */
2214 for (j = 0; j < count; j ++)
2215 {
2216 rtx addr;
2217 int ofs = (count - j - 1) * (TARGET_LARGE ? 4 : 2);
2218
2219 if (ofs)
2220 addr = gen_rtx_PLUS (Pmode, sp, GEN_INT (ofs));
2221 else
2222 addr = stack_pointer_rtx;
2223
6956ee35 2224 XVECEXP (note, 0, j + 1) =
d1f9b275 2225 F (gen_rtx_SET (gen_rtx_MEM (Pmode, addr),
e4a25868 2226 gen_rtx_REG (Pmode, i - j)) );
2227 }
2228
2229 add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
2230 i -= count - 1;
2231 }
2232 else
2233 F (emit_insn (gen_push (gen_rtx_REG (Pmode, i))));
2234 }
2235
2236 if (frame_pointer_needed)
2237 F (emit_move_insn (gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM), sp));
2238
2239 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
2240
2241 increment_stack (- fs);
2242
2243 emit_insn (gen_prologue_end_marker ());
2244}
2245
2246void
2247msp430_expand_epilogue (int is_eh)
2248{
2249 int i;
2250 int fs;
2251 int helper_n = 0;
2252
62b2ccbe 2253 if (is_naked_func ())
f87a602b 2254 {
2255 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2256 examines the output of the gen_epilogue() function. */
2257 emit_insn (gen_rtx_CLOBBER (VOIDmode, GEN_INT (0)));
2258 return;
2259 }
62b2ccbe 2260
e4a25868 2261 if (cfun->machine->need_to_save [10])
2262 {
2263 /* Check for a helper function. */
9b52871c 2264 helper_n = 7; /* For when the loop below never sees a match. */
e4a25868 2265 for (i = 9; i >= 4; i--)
2266 if (!cfun->machine->need_to_save [i])
2267 {
2268 helper_n = 10 - i;
2269 for (; i >= 4; i--)
2270 if (cfun->machine->need_to_save [i])
2271 {
2272 helper_n = 0;
2273 break;
2274 }
2275 break;
2276 }
2277 }
2278
2279 emit_insn (gen_epilogue_start_marker ());
2280
9d636c05 2281 if (cfun->decl && strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun->decl)), "main") == 0)
2282 emit_insn (gen_msp430_refsym_need_exit ());
2283
0a9aab6d 2284 if (is_wakeup_func ())
2285 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
2286 status register current residing on the stack. When this function
2287 executes its RETI instruction the SR will be updated with this saved
2288 value, thus ensuring that the processor is woken up from any low power
2289 state in which it may be residing. */
2290 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
2291
e4a25868 2292 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
2293
2294 increment_stack (fs);
2295
2296 if (is_eh)
2297 {
2298 /* We need to add the right "SP" register save just after the
2299 regular ones, so that when we pop it off we're in the EH
2300 return frame, not this one. This overwrites our own return
2301 address, but we're not going to be returning anyway. */
2302 rtx r12 = gen_rtx_REG (Pmode, 12);
2303 rtx (*addPmode)(rtx, rtx, rtx) = TARGET_LARGE ? gen_addpsi3 : gen_addhi3;
2304
2305 /* R12 will hold the new SP. */
2306 i = cfun->machine->framesize_regs;
2307 emit_move_insn (r12, stack_pointer_rtx);
2308 emit_insn (addPmode (r12, r12, EH_RETURN_STACKADJ_RTX));
2309 emit_insn (addPmode (r12, r12, GEN_INT (i)));
2310 emit_move_insn (gen_rtx_MEM (Pmode, plus_constant (Pmode, stack_pointer_rtx, i)), r12);
2311 }
2312
2313 for (i = 4; i <= 15; i++)
2314 if (cfun->machine->need_to_save [i])
2315 {
2316 int seq, count;
2317
2318 for (seq = i + 1; seq <= 15 && cfun->machine->need_to_save[seq]; seq ++)
2319 ;
2320 count = seq - i;
2321
2322 if (msp430x)
2323 {
abe1609f 2324 /* Note: With TARGET_LARGE we still use
2325 POPM as POPX.A is two bytes bigger. */
2326 emit_insn (gen_popm (stack_pointer_rtx, GEN_INT (seq - 1),
e4a25868 2327 GEN_INT (count)));
2328 i += count - 1;
2329 }
2330 else if (i == 11 - helper_n
62b2ccbe 2331 && ! msp430_is_interrupt_func ()
2332 && ! is_reentrant_func ()
2333 && ! is_critical_func ()
e4a25868 2334 && crtl->args.pretend_args_size == 0
2335 /* Calling the helper takes as many bytes as the POP;RET sequence. */
9b52871c 2336 && helper_n > 1
e4a25868 2337 && !is_eh)
2338 {
2339 emit_insn (gen_epilogue_helper (GEN_INT (helper_n)));
2340 return;
2341 }
2342 else
2343 emit_insn (gen_pop (gen_rtx_REG (Pmode, i)));
2344 }
2345
2346 if (is_eh)
2347 {
2348 /* Also pop SP, which puts us into the EH return frame. Except
2349 that you can't "pop" sp, you have to just load it off the
2350 stack. */
2351 emit_move_insn (stack_pointer_rtx, gen_rtx_MEM (Pmode, stack_pointer_rtx));
2352 }
2353
2354 if (crtl->args.pretend_args_size)
2355 emit_insn (gen_swap_and_shrink ());
62b2ccbe 2356
2357 if (is_critical_func ())
2358 emit_insn (gen_pop_intr_state ());
2359 else if (is_reentrant_func ())
2360 emit_insn (gen_enable_interrupts ());
2361
e4a25868 2362 emit_jump_insn (gen_msp_return ());
2363}
2364
2365/* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
2366 m32c_emit_eh_epilogue. */
2367rtx
2368msp430_eh_return_stackadj_rtx (void)
2369{
2370 if (!cfun->machine->eh_stack_adjust)
2371 {
2372 rtx sa;
2373
2374 sa = gen_rtx_REG (Pmode, 15);
2375 cfun->machine->eh_stack_adjust = sa;
2376 }
2377 return cfun->machine->eh_stack_adjust;
2378}
2379
2380/* This function is called before reload, to "fix" the stack in
2381 preparation for an EH return. */
2382void
2383msp430_expand_eh_return (rtx eh_handler)
2384{
2385 /* These are all Pmode */
2386 rtx ap, sa, ra, tmp;
2387
2388 ap = arg_pointer_rtx;
2389 sa = msp430_eh_return_stackadj_rtx ();
2390 ra = eh_handler;
2391
2392 tmp = ap;
2393 tmp = gen_rtx_PLUS (Pmode, ap, sa);
2394 tmp = plus_constant (Pmode, tmp, TARGET_LARGE ? -4 : -2);
2395 tmp = gen_rtx_MEM (Pmode, tmp);
2396 emit_move_insn (tmp, ra);
2397}
2398
f6bba390 2399#undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
2400#define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
2401void
2402msp430_init_dwarf_reg_sizes_extra (tree address)
2403{
2404 int i;
2405 rtx addr = expand_normal (address);
2406 rtx mem = gen_rtx_MEM (BLKmode, addr);
2407
7ed86ba5 2408 /* This needs to match msp430_unwind_word_mode (above). */
f6bba390 2409 if (!msp430x)
2410 return;
2411
2412 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2413 {
2414 unsigned int dnum = DWARF_FRAME_REGNUM (i);
2415 unsigned int rnum = DWARF2_FRAME_REG_OUT (dnum, 1);
2416
2417 if (rnum < DWARF_FRAME_REGISTERS)
2418 {
2419 HOST_WIDE_INT offset = rnum * GET_MODE_SIZE (QImode);
2420
2421 emit_move_insn (adjust_address (mem, QImode, offset),
2422 gen_int_mode (4, QImode));
2423 }
2424 }
2425}
2426
e4a25868 2427/* This is a list of MD patterns that implement fixed-count shifts. */
62b2ccbe 2428static struct
2429{
e4a25868 2430 const char *name;
2431 int count;
2432 int need_430x;
2433 rtx (*genfunc)(rtx,rtx);
62b2ccbe 2434}
2435 const_shift_helpers[] =
2436{
9d247a3d 2437#define CSH(N,C,X,G) { "__mspabi_" N, C, X, gen_##G }
e4a25868 2438
2439 CSH ("slli", 1, 1, slli_1),
2440 CSH ("slll", 1, 1, slll_1),
2441 CSH ("slll", 2, 1, slll_2),
2442
2443 CSH ("srai", 1, 0, srai_1),
2444 CSH ("sral", 1, 0, sral_1),
2445 CSH ("sral", 2, 0, sral_2),
2446
2447 CSH ("srll", 1, 0, srll_1),
2448 CSH ("srll", 2, 1, srll_2x),
2449 { 0, 0, 0, 0 }
2450#undef CSH
2451};
2452
2453/* The MSP430 ABI defines a number of helper functions that should be
2454 used for, for example, 32-bit shifts. This function is called to
2455 emit such a function, using the table above to optimize some
2456 cases. */
2457void
2458msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variants)
2459{
2460 rtx c, f;
2461 char *helper_const = NULL;
4ccf69d7 2462 int arg1 = 12;
e4a25868 2463 int arg2 = 13;
2464 int arg1sz = 1;
3754d046 2465 machine_mode arg0mode = GET_MODE (operands[0]);
2466 machine_mode arg1mode = GET_MODE (operands[1]);
2467 machine_mode arg2mode = GET_MODE (operands[2]);
e4a25868 2468 int have_430x = msp430x ? 1 : 0;
2469
2470 if (CONST_INT_P (operands[2]))
2471 {
2472 int i;
2473
2474 for (i=0; const_shift_helpers[i].name; i++)
2475 {
2476 if (const_shift_helpers[i].need_430x <= have_430x
2477 && strcmp (helper_name, const_shift_helpers[i].name) == 0
2478 && INTVAL (operands[2]) == const_shift_helpers[i].count)
2479 {
2480 emit_insn (const_shift_helpers[i].genfunc (operands[0], operands[1]));
2481 return;
2482 }
2483 }
2484 }
2485
2486 if (arg1mode == VOIDmode)
2487 arg1mode = arg0mode;
2488 if (arg2mode == VOIDmode)
2489 arg2mode = arg0mode;
2490
2491 if (arg1mode == SImode)
2492 {
2493 arg2 = 14;
2494 arg1sz = 2;
2495 }
4ccf69d7 2496 else if (arg1mode == DImode)
2497 {
2498 /* Shift value in R8:R11, shift amount in R12. */
2499 arg1 = 8;
2500 arg1sz = 4;
2501 arg2 = 12;
2502 }
e4a25868 2503
2504 if (const_variants
2505 && CONST_INT_P (operands[2])
2506 && INTVAL (operands[2]) >= 1
2507 && INTVAL (operands[2]) <= 15)
2508 {
2509 /* Note that the INTVAL is limited in value and length by the conditional above. */
2510 int len = strlen (helper_name) + 4;
2511 helper_const = (char *) xmalloc (len);
9b52871c 2512 snprintf (helper_const, len, "%s_%d", helper_name, (int) INTVAL (operands[2]));
e4a25868 2513 }
2514
4ccf69d7 2515 emit_move_insn (gen_rtx_REG (arg1mode, arg1),
e4a25868 2516 operands[1]);
2517 if (!helper_const)
2518 emit_move_insn (gen_rtx_REG (arg2mode, arg2),
2519 operands[2]);
2520
2521 c = gen_call_value_internal (gen_rtx_REG (arg0mode, 12),
2522 gen_rtx_SYMBOL_REF (VOIDmode, helper_const ? helper_const : helper_name),
2523 GEN_INT (0));
2524 c = emit_call_insn (c);
2525 RTL_CONST_CALL_P (c) = 1;
2526
2527 f = 0;
4ccf69d7 2528 use_regs (&f, arg1, arg1sz);
e4a25868 2529 if (!helper_const)
2530 use_regs (&f, arg2, 1);
2531 add_function_usage_to (c, f);
2532
2533 emit_move_insn (operands[0],
4ccf69d7 2534 /* Return value will always start in R12. */
e4a25868 2535 gen_rtx_REG (arg0mode, 12));
2536}
2537
2538/* Called by cbranch<mode>4 to coerce operands into usable forms. */
2539void
3754d046 2540msp430_fixup_compare_operands (machine_mode my_mode, rtx * operands)
e4a25868 2541{
2542 /* constants we're looking for, not constants which are allowed. */
2543 int const_op_idx = 1;
2544
2545 if (msp430_reversible_cmp_operator (operands[0], VOIDmode))
2546 const_op_idx = 2;
2547
2548 if (GET_CODE (operands[const_op_idx]) != REG
2549 && GET_CODE (operands[const_op_idx]) != MEM)
2550 operands[const_op_idx] = copy_to_mode_reg (my_mode, operands[const_op_idx]);
2551}
2552
2553/* Simplify_gen_subreg() doesn't handle memory references the way we
2554 need it to below, so we use this function for when we must get a
2555 valid subreg in a "natural" state. */
2556rtx
3754d046 2557msp430_subreg (machine_mode mode, rtx r, machine_mode omode, int byte)
e4a25868 2558{
2559 rtx rv;
2560
2561 if (GET_CODE (r) == SUBREG
2562 && SUBREG_BYTE (r) == 0)
2563 {
2564 rtx ireg = SUBREG_REG (r);
3754d046 2565 machine_mode imode = GET_MODE (ireg);
e4a25868 2566
2567 /* special case for (HI (SI (PSI ...), 0)) */
2568 if (imode == PSImode
2569 && mode == HImode
2570 && byte == 0)
2571 rv = gen_rtx_SUBREG (mode, ireg, byte);
2572 else
2573 rv = simplify_gen_subreg (mode, ireg, imode, byte);
2574 }
2575 else if (GET_CODE (r) == MEM)
2576 rv = adjust_address (r, mode, byte);
52ba9937 2577 else if (GET_CODE (r) == SYMBOL_REF
2578 && (byte == 0 || byte == 2)
2579 && mode == HImode)
2580 {
2581 rv = gen_rtx_ZERO_EXTRACT (HImode, r, GEN_INT (16), GEN_INT (8*byte));
2582 rv = gen_rtx_CONST (HImode, r);
2583 }
e4a25868 2584 else
2585 rv = simplify_gen_subreg (mode, r, omode, byte);
2586
2587 if (!rv)
2588 gcc_unreachable ();
2589
2590 return rv;
2591}
2592
2593/* Called by movsi_x to generate the HImode operands. */
2594void
2595msp430_split_movsi (rtx *operands)
2596{
2597 rtx op00, op02, op10, op12;
2598
2599 op00 = msp430_subreg (HImode, operands[0], SImode, 0);
2600 op02 = msp430_subreg (HImode, operands[0], SImode, 2);
2601
2602 if (GET_CODE (operands[1]) == CONST
2603 || GET_CODE (operands[1]) == SYMBOL_REF)
2604 {
2605 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
2606 op10 = gen_rtx_CONST (HImode, op10);
2607 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
2608 op12 = gen_rtx_CONST (HImode, op12);
2609 }
2610 else
2611 {
2612 op10 = msp430_subreg (HImode, operands[1], SImode, 0);
2613 op12 = msp430_subreg (HImode, operands[1], SImode, 2);
2614 }
2615
2616 if (rtx_equal_p (operands[0], operands[1]))
2617 {
2618 operands[2] = op02;
2619 operands[4] = op12;
2620 operands[3] = op00;
2621 operands[5] = op10;
2622 }
2623 else if (rtx_equal_p (op00, op12)
2624 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
2625 || (REG_P (op00) && reg_mentioned_p (op00, op10))
2626 /* Or storing (rN) into mem (rN). */
2627 || (REG_P (op10) && reg_mentioned_p (op10, op00))
2628 )
2629 {
2630 operands[2] = op02;
2631 operands[4] = op12;
2632 operands[3] = op00;
2633 operands[5] = op10;
2634 }
2635 else
2636 {
2637 operands[2] = op00;
2638 operands[4] = op10;
2639 operands[3] = op02;
2640 operands[5] = op12;
2641 }
2642}
2643
2644\f
e4a25868 2645/* The MSPABI specifies the names of various helper functions, many of
2646 which are compatible with GCC's helpers. This table maps the GCC
2647 name to the MSPABI name. */
2648static const struct
2649{
2650 char const * const gcc_name;
2651 char const * const ti_name;
2652}
2653 helper_function_name_mappings [] =
2654{
2655 /* Floating point to/from integer conversions. */
2656 { "__truncdfsf2", "__mspabi_cvtdf" },
2657 { "__extendsfdf2", "__mspabi_cvtfd" },
2658 { "__fixdfhi", "__mspabi_fixdi" },
2659 { "__fixdfsi", "__mspabi_fixdli" },
2660 { "__fixdfdi", "__mspabi_fixdlli" },
2661 { "__fixunsdfhi", "__mspabi_fixdu" },
2662 { "__fixunsdfsi", "__mspabi_fixdul" },
2663 { "__fixunsdfdi", "__mspabi_fixdull" },
2664 { "__fixsfhi", "__mspabi_fixfi" },
2665 { "__fixsfsi", "__mspabi_fixfli" },
2666 { "__fixsfdi", "__mspabi_fixflli" },
2667 { "__fixunsfhi", "__mspabi_fixfu" },
2668 { "__fixunsfsi", "__mspabi_fixful" },
2669 { "__fixunsfdi", "__mspabi_fixfull" },
2670 { "__floathisf", "__mspabi_fltif" },
2671 { "__floatsisf", "__mspabi_fltlif" },
2672 { "__floatdisf", "__mspabi_fltllif" },
2673 { "__floathidf", "__mspabi_fltid" },
2674 { "__floatsidf", "__mspabi_fltlid" },
2675 { "__floatdidf", "__mspabi_fltllid" },
2676 { "__floatunhisf", "__mspabi_fltuf" },
2677 { "__floatunsisf", "__mspabi_fltulf" },
2678 { "__floatundisf", "__mspabi_fltullf" },
2679 { "__floatunhidf", "__mspabi_fltud" },
2680 { "__floatunsidf", "__mspabi_fltuld" },
2681 { "__floatundidf", "__mspabi_fltulld" },
2682
2683 /* Floating point comparisons. */
2684 /* GCC uses individual functions for each comparison, TI uses one
2685 compare <=> function. */
2686
2687 /* Floating point arithmatic */
2688 { "__adddf3", "__mspabi_addd" },
2689 { "__addsf3", "__mspabi_addf" },
2690 { "__divdf3", "__mspabi_divd" },
2691 { "__divsf3", "__mspabi_divf" },
2692 { "__muldf3", "__mspabi_mpyd" },
2693 { "__mulsf3", "__mspabi_mpyf" },
2694 { "__subdf3", "__mspabi_subd" },
2695 { "__subsf3", "__mspabi_subf" },
2696 /* GCC does not use helper functions for negation */
2697
2698 /* Integer multiply, divide, remainder. */
e4a25868 2699 { "__mulhi3", "__mspabi_mpyi" },
2700 { "__mulsi3", "__mspabi_mpyl" },
2701 { "__muldi3", "__mspabi_mpyll" },
2702#if 0
2703 /* Clarify signed vs unsigned first. */
2704 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
2705 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
2706#endif
2707
2708 { "__divhi3", "__mspabi_divi" },
2709 { "__divsi3", "__mspabi_divli" },
2710 { "__divdi3", "__mspabi_divlli" },
2711 { "__udivhi3", "__mspabi_divu" },
7ed86ba5 2712 { "__udivsi3", "__mspabi_divul" },
2713 { "__udivdi3", "__mspabi_divull" },
e4a25868 2714 { "__modhi3", "__mspabi_remi" },
2715 { "__modsi3", "__mspabi_remli" },
2716 { "__moddi3", "__mspabi_remlli" },
2717 { "__umodhi3", "__mspabi_remu" },
2718 { "__umodsi3", "__mspabi_remul" },
2719 { "__umoddi3", "__mspabi_remull" },
2720
2721 /* Bitwise operations. */
2722 /* Rotation - no rotation support yet. */
2723 /* Logical left shift - gcc already does these itself. */
2724 /* Arithmetic left shift - gcc already does these itself. */
2725 /* Arithmetic right shift - gcc already does these itself. */
2726
2727 { NULL, NULL }
2728};
2729
f87a602b 2730/* Returns true if the current MCU supports an F5xxx series
2731 hardware multiper. */
2732
6956ee35 2733bool
c05cbf30 2734msp430_use_f5_series_hwmult (void)
6956ee35 2735{
f87a602b 2736 static const char * cached_match = NULL;
2737 static bool cached_result;
2738
bdc549ca 2739 if (msp430_hwmult_type == MSP430_HWMULT_F5SERIES)
c05cbf30 2740 return true;
2741
bdc549ca 2742 if (target_mcu == NULL || msp430_hwmult_type != MSP430_HWMULT_AUTO)
6956ee35 2743 return false;
c05cbf30 2744
f87a602b 2745 if (target_mcu == cached_match)
2746 return cached_result;
2747
2748 cached_match = target_mcu;
2749
2750 if (strncasecmp (target_mcu, "msp430f5", 8) == 0)
2751 return cached_result = true;
c2e656e1 2752 if (strncasecmp (target_mcu, "msp430fr5", 9) == 0)
2753 return cached_result = true;
2754 if (strncasecmp (target_mcu, "msp430f6", 8) == 0)
2755 return cached_result = true;
f87a602b 2756
bb4cc462 2757 msp430_extract_mcu_data (target_mcu);
f87a602b 2758
bb4cc462 2759 if (extracted_mcu_data.name != NULL)
2760 return cached_result = extracted_mcu_data.hwmpy == 8;
f87a602b 2761
2762 return cached_result = false;
6956ee35 2763}
2764
f87a602b 2765/* Returns true if the current MCU has a second generation
2766 32-bit hardware multiplier. */
2767
6956ee35 2768static bool
c05cbf30 2769use_32bit_hwmult (void)
6956ee35 2770{
f87a602b 2771 static const char * cached_match = NULL;
2772 static bool cached_result;
c05cbf30 2773
bdc549ca 2774 if (msp430_hwmult_type == MSP430_HWMULT_LARGE)
c05cbf30 2775 return true;
2776
bdc549ca 2777 if (target_mcu == NULL || msp430_hwmult_type != MSP430_HWMULT_AUTO)
6956ee35 2778 return false;
2779
f87a602b 2780 if (target_mcu == cached_match)
2781 return cached_result;
2782
2783 cached_match = target_mcu;
02059be0 2784
bb4cc462 2785 msp430_extract_mcu_data (target_mcu);
2786 if (extracted_mcu_data.name != NULL)
2787 return cached_result = extracted_mcu_data.hwmpy == 4;
6956ee35 2788
f87a602b 2789 return cached_result = false;
2790}
2791
2792/* Returns true if the current MCU does not have a
2793 hardware multiplier of any kind. */
2794
2795static bool
2796msp430_no_hwmult (void)
2797{
f87a602b 2798 static const char * cached_match = NULL;
2799 static bool cached_result;
f87a602b 2800
bdc549ca 2801 if (msp430_hwmult_type == MSP430_HWMULT_NONE)
f87a602b 2802 return true;
2803
bdc549ca 2804 if (msp430_hwmult_type != MSP430_HWMULT_AUTO)
f87a602b 2805 return false;
2806
7ed86ba5 2807 if (target_mcu == NULL)
2808 return true;
2809
f87a602b 2810 if (target_mcu == cached_match)
2811 return cached_result;
2812
2813 cached_match = target_mcu;
f87a602b 2814
bb4cc462 2815 msp430_extract_mcu_data (target_mcu);
2816 if (extracted_mcu_data.name != NULL)
2817 return cached_result = extracted_mcu_data.hwmpy == 0;
02059be0 2818
2819 /* If we do not recognise the MCU name, we assume that it does not support
2820 any kind of hardware multiply - this is the safest assumption to make. */
2821 return cached_result = true;
6956ee35 2822}
2823
e4a25868 2824/* This function does the same as the default, but it will replace GCC
2825 function names with the MSPABI-specified ones. */
f87a602b 2826
e4a25868 2827void
2828msp430_output_labelref (FILE *file, const char *name)
2829{
2830 int i;
2831
2832 for (i = 0; helper_function_name_mappings [i].gcc_name; i++)
6956ee35 2833 if (strcmp (helper_function_name_mappings [i].gcc_name, name) == 0)
e4a25868 2834 {
6956ee35 2835 name = helper_function_name_mappings [i].ti_name;
2836 break;
e4a25868 2837 }
2838
6956ee35 2839 /* If we have been given a specific MCU name then we may be
2840 able to make use of its hardware multiply capabilities. */
bdc549ca 2841 if (msp430_hwmult_type != MSP430_HWMULT_NONE)
6956ee35 2842 {
2843 if (strcmp ("__mspabi_mpyi", name) == 0)
2844 {
c05cbf30 2845 if (msp430_use_f5_series_hwmult ())
6956ee35 2846 name = "__mulhi2_f5";
f87a602b 2847 else if (! msp430_no_hwmult ())
6956ee35 2848 name = "__mulhi2";
2849 }
2850 else if (strcmp ("__mspabi_mpyl", name) == 0)
2851 {
c05cbf30 2852 if (msp430_use_f5_series_hwmult ())
6956ee35 2853 name = "__mulsi2_f5";
c05cbf30 2854 else if (use_32bit_hwmult ())
6956ee35 2855 name = "__mulsi2_hw32";
f87a602b 2856 else if (! msp430_no_hwmult ())
6956ee35 2857 name = "__mulsi2";
2858 }
2859 }
2860
8bf9f89c 2861 if (user_label_prefix[0] != 0)
2862 fputs (user_label_prefix, file);
2863
e4a25868 2864 fputs (name, file);
2865}
2866
9b52871c 2867/* Common code for msp430_print_operand... */
e4a25868 2868
e4a25868 2869static void
9b52871c 2870msp430_print_operand_raw (FILE * file, rtx op)
e4a25868 2871{
0a9aab6d 2872 HOST_WIDE_INT i;
e4a25868 2873
2874 switch (GET_CODE (op))
2875 {
2876 case REG:
2877 fprintf (file, "%s", reg_names [REGNO (op)]);
2878 break;
2879
2880 case CONST_INT:
2881 i = INTVAL (op);
2882 if (TARGET_ASM_HEX)
0a9aab6d 2883 fprintf (file, "%#" HOST_WIDE_INT_PRINT "x", i);
e4a25868 2884 else
0a9aab6d 2885 fprintf (file, "%" HOST_WIDE_INT_PRINT "d", i);
e4a25868 2886 break;
2887
2888 case CONST:
2889 case PLUS:
2890 case MINUS:
2891 case SYMBOL_REF:
2892 case LABEL_REF:
2893 output_addr_const (file, op);
2894 break;
2895
2896 default:
2897 print_rtl (file, op);
2898 break;
2899 }
2900}
2901
db879ec7 2902#undef TARGET_ASM_ALIGNED_PSI_OP
2903#define TARGET_ASM_ALIGNED_PSI_OP "\t.long\t"
2904#undef TARGET_ASM_UNALIGNED_PSI_OP
2905#define TARGET_ASM_UNALIGNED_PSI_OP TARGET_ASM_ALIGNED_PSI_OP
2906
9b52871c 2907#undef TARGET_PRINT_OPERAND_ADDRESS
2908#define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
2909
2910/* Output to stdio stream FILE the assembler syntax for an
2911 instruction operand that is a memory reference whose address
2912 is ADDR. */
2913
2914static void
3c047fe9 2915msp430_print_operand_addr (FILE * file, machine_mode /*mode*/, rtx addr)
9b52871c 2916{
2917 switch (GET_CODE (addr))
2918 {
2919 case PLUS:
2920 msp430_print_operand_raw (file, XEXP (addr, 1));
2921 gcc_assert (REG_P (XEXP (addr, 0)));
2922 fprintf (file, "(%s)", reg_names [REGNO (XEXP (addr, 0))]);
2923 return;
2924
2925 case REG:
2926 fprintf (file, "@");
2927 break;
2928
2929 case CONST:
2930 case CONST_INT:
2931 case SYMBOL_REF:
2932 case LABEL_REF:
2933 fprintf (file, "&");
2934 break;
2935
2936 default:
2937 break;
2938 }
2939
2940 msp430_print_operand_raw (file, addr);
2941}
2942
2943#undef TARGET_PRINT_OPERAND
2944#define TARGET_PRINT_OPERAND msp430_print_operand
2945
b2cc50a9 2946/* A low 16-bits of int/lower of register pair
2947 B high 16-bits of int/higher of register pair
2948 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
2949 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
2950 H like %B (for backwards compatibility)
2951 I inverse of value
50753af6 2952 J an integer without a # prefix
b2cc50a9 2953 L like %A (for backwards compatibility)
2954 O offset of the top of the stack
2955 Q like X but generates an A postfix
2956 R inverse of condition code, unsigned.
2957 X X instruction postfix in large mode
2958 Y value - 4
2959 Z value - 1
2960 b .B or .W or .A, depending upon the mode
2961 p bit position
2962 r inverse of condition code
2963 x like X but only for pointers. */
2964
e4a25868 2965static void
2966msp430_print_operand (FILE * file, rtx op, int letter)
2967{
2968 rtx addr;
2969
2970 /* We can't use c, n, a, or l. */
2971 switch (letter)
2972 {
2973 case 'Z':
2974 gcc_assert (CONST_INT_P (op));
2975 /* Print the constant value, less one. */
2976 fprintf (file, "#%ld", INTVAL (op) - 1);
2977 return;
2978 case 'Y':
2979 gcc_assert (CONST_INT_P (op));
2980 /* Print the constant value, less four. */
2981 fprintf (file, "#%ld", INTVAL (op) - 4);
2982 return;
e4a25868 2983 case 'I':
2984 if (GET_CODE (op) == CONST_INT)
2985 {
2986 /* Inverse of constants */
2987 int i = INTVAL (op);
2988 fprintf (file, "%d", ~i);
2989 return;
2990 }
2991 op = XEXP (op, 0);
2992 break;
2993 case 'r': /* Conditional jump where the condition is reversed. */
2994 switch (GET_CODE (op))
2995 {
2996 case EQ: fprintf (file, "NE"); break;
2997 case NE: fprintf (file, "EQ"); break;
2998 case GEU: fprintf (file, "LO"); break;
2999 case LTU: fprintf (file, "HS"); break;
3000 case GE: fprintf (file, "L"); break;
3001 case LT: fprintf (file, "GE"); break;
3002 /* Assume these have reversed operands. */
3003 case GTU: fprintf (file, "HS"); break;
3004 case LEU: fprintf (file, "LO"); break;
3005 case GT: fprintf (file, "GE"); break;
3006 case LE: fprintf (file, "L"); break;
3007 default:
9b52871c 3008 msp430_print_operand_raw (file, op);
e4a25868 3009 break;
3010 }
3011 return;
3012 case 'R': /* Conditional jump where the operands are reversed. */
3013 switch (GET_CODE (op))
3014 {
3015 case GTU: fprintf (file, "LO"); break;
3016 case LEU: fprintf (file, "HS"); break;
3017 case GT: fprintf (file, "L"); break;
3018 case LE: fprintf (file, "GE"); break;
3019 default:
9b52871c 3020 msp430_print_operand_raw (file, op);
e4a25868 3021 break;
3022 }
3023 return;
3024 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
3025 gcc_assert (CONST_INT_P (op));
3026 fprintf (file, "#%d", 1 << INTVAL (op));
3027 return;
b2cc50a9 3028 case 'b':
e4a25868 3029 switch (GET_MODE (op))
3030 {
916ace94 3031 case E_QImode: fprintf (file, ".B"); return;
3032 case E_HImode: fprintf (file, ".W"); return;
3033 case E_PSImode: fprintf (file, ".A"); return;
3034 case E_SImode: fprintf (file, ".A"); return;
e4a25868 3035 default:
3036 return;
3037 }
b2cc50a9 3038 case 'A':
e4a25868 3039 case 'L': /* Low half. */
3040 switch (GET_CODE (op))
3041 {
3042 case MEM:
3043 op = adjust_address (op, Pmode, 0);
3044 break;
3045 case REG:
3046 break;
3047 case CONST_INT:
3048 op = GEN_INT (INTVAL (op) & 0xffff);
3049 letter = 0;
3050 break;
3051 default:
3052 /* If you get here, figure out a test case :-) */
3053 gcc_unreachable ();
3054 }
3055 break;
b2cc50a9 3056 case 'B':
e4a25868 3057 case 'H': /* high half */
3058 switch (GET_CODE (op))
3059 {
3060 case MEM:
3061 op = adjust_address (op, Pmode, 2);
3062 break;
3063 case REG:
3064 op = gen_rtx_REG (Pmode, REGNO (op) + 1);
3065 break;
3066 case CONST_INT:
3067 op = GEN_INT (INTVAL (op) >> 16);
3068 letter = 0;
3069 break;
3070 default:
3071 /* If you get here, figure out a test case :-) */
3072 gcc_unreachable ();
3073 }
3074 break;
b2cc50a9 3075 case 'C':
3076 switch (GET_CODE (op))
3077 {
3078 case MEM:
3079 op = adjust_address (op, Pmode, 3);
3080 break;
3081 case REG:
3082 op = gen_rtx_REG (Pmode, REGNO (op) + 2);
3083 break;
3084 case CONST_INT:
6956ee35 3085 op = GEN_INT ((long long) INTVAL (op) >> 32);
b2cc50a9 3086 letter = 0;
3087 break;
3088 default:
3089 /* If you get here, figure out a test case :-) */
3090 gcc_unreachable ();
3091 }
3092 break;
3093 case 'D':
3094 switch (GET_CODE (op))
3095 {
3096 case MEM:
3097 op = adjust_address (op, Pmode, 4);
3098 break;
3099 case REG:
3100 op = gen_rtx_REG (Pmode, REGNO (op) + 3);
3101 break;
3102 case CONST_INT:
6956ee35 3103 op = GEN_INT ((long long) INTVAL (op) >> 48);
b2cc50a9 3104 letter = 0;
3105 break;
3106 default:
3107 /* If you get here, figure out a test case :-) */
3108 gcc_unreachable ();
3109 }
3110 break;
e4a25868 3111
3112 case 'X':
3113 /* This is used to turn, for example, an ADD opcode into an ADDX
3114 opcode when we're using 20-bit addresses. */
f6bba390 3115 if (TARGET_LARGE || GET_MODE (op) == PSImode)
e4a25868 3116 fprintf (file, "X");
3117 /* We don't care which operand we use, but we want 'X' in the MD
3118 file, so we do it this way. */
3119 return;
3120
3121 case 'x':
3122 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
d16d2561 3123 if (GET_MODE (op) == PSImode)
e4a25868 3124 fprintf (file, "X");
3125 return;
3126
b2cc50a9 3127 case 'Q':
e4a25868 3128 /* Likewise, for BR -> BRA. */
3129 if (TARGET_LARGE)
3130 fprintf (file, "A");
3131 return;
62b2ccbe 3132
3133 case 'O':
3134 /* Computes the offset to the top of the stack for the current frame.
3135 This has to be done here rather than in, say, msp430_expand_builtin()
3136 because builtins are expanded before the frame layout is determined. */
3137 fprintf (file, "%d",
3138 msp430_initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM)
c0b06633 3139 - (TARGET_LARGE ? 4 : 2));
9b52871c 3140 return;
b2cc50a9 3141
50753af6 3142 case 'J':
3143 gcc_assert (GET_CODE (op) == CONST_INT);
b2cc50a9 3144 case 0:
3145 break;
3146 default:
3147 output_operand_lossage ("invalid operand prefix");
3148 return;
e4a25868 3149 }
3150
3151 switch (GET_CODE (op))
3152 {
3153 case REG:
9b52871c 3154 msp430_print_operand_raw (file, op);
e4a25868 3155 break;
3156
3157 case MEM:
3158 addr = XEXP (op, 0);
3c047fe9 3159 msp430_print_operand_addr (file, GET_MODE (op), addr);
e4a25868 3160 break;
3161
e4a25868 3162 case CONST:
58f45145 3163 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTRACT)
3164 {
3165 op = XEXP (op, 0);
3166 switch (INTVAL (XEXP (op, 2)))
3167 {
3168 case 0:
3169 fprintf (file, "#lo (");
3170 msp430_print_operand_raw (file, XEXP (op, 0));
3171 fprintf (file, ")");
3172 break;
3173
3174 case 16:
3175 fprintf (file, "#hi (");
3176 msp430_print_operand_raw (file, XEXP (op, 0));
3177 fprintf (file, ")");
3178 break;
3179
3180 default:
3181 output_operand_lossage ("invalid zero extract");
3182 break;
3183 }
3184 break;
3185 }
3186 /* Fall through. */
3187 case CONST_INT:
e4a25868 3188 case SYMBOL_REF:
3189 case LABEL_REF:
3190 if (letter == 0)
3191 fprintf (file, "#");
9b52871c 3192 msp430_print_operand_raw (file, op);
e4a25868 3193 break;
3194
3195 case EQ: fprintf (file, "EQ"); break;
3196 case NE: fprintf (file, "NE"); break;
3197 case GEU: fprintf (file, "HS"); break;
3198 case LTU: fprintf (file, "LO"); break;
3199 case GE: fprintf (file, "GE"); break;
3200 case LT: fprintf (file, "L"); break;
3201
3202 default:
3203 print_rtl (file, op);
3204 break;
3205 }
e4a25868 3206}
3207
3208\f
3209/* Frame stuff. */
3210
3211rtx
3212msp430_return_addr_rtx (int count)
3213{
3214 int ra_size;
3215 if (count)
3216 return NULL_RTX;
3217
3218 ra_size = TARGET_LARGE ? 4 : 2;
3219 if (crtl->args.pretend_args_size)
3220 ra_size += 2;
3221
3222 return gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, arg_pointer_rtx, GEN_INT (- ra_size)));
3223}
3224
3225rtx
3226msp430_incoming_return_addr_rtx (void)
3227{
3228 return gen_rtx_MEM (Pmode, stack_pointer_rtx);
3229}
3230\f
3231/* Instruction generation stuff. */
3232
3233/* Generate a sequence of instructions to sign-extend an HI
3234 value into an SI value. Handles the tricky case where
3235 we are overwriting the destination. */
3236
3237const char *
3238msp430x_extendhisi (rtx * operands)
3239{
3240 if (REGNO (operands[0]) == REGNO (operands[1]))
3241 /* Low word of dest == source word. */
abe1609f 3242 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
e4a25868 3243
3244 if (! msp430x)
3245 /* Note: This sequence is approximately the same length as invoking a helper
3246 function to perform the sign-extension, as in:
6956ee35 3247
e4a25868 3248 MOV.W %1, %L0
3249 MOV.W %1, r12
3250 CALL __mspabi_srai_15
3251 MOV.W r12, %H0
3252
3253 but this version does not involve any function calls or using argument
3254 registers, so it reduces register pressure. */
abe1609f 3255 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
6956ee35 3256
e4a25868 3257 if (REGNO (operands[0]) + 1 == REGNO (operands[1]))
3258 /* High word of dest == source word. */
abe1609f 3259 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
e4a25868 3260
3261 /* No overlap between dest and source. */
abe1609f 3262 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
e4a25868 3263}
3264
3265/* Likewise for logical right shifts. */
3266const char *
3267msp430x_logical_shift_right (rtx amount)
3268{
3269 /* The MSP430X's logical right shift instruction - RRUM - does
3270 not use an extension word, so we cannot encode a repeat count.
3271 Try various alternatives to work around this. If the count
3272 is in a register we are stuck, hence the assert. */
3273 gcc_assert (CONST_INT_P (amount));
3274
3275 if (INTVAL (amount) <= 0
3276 || INTVAL (amount) >= 16)
3277 return "# nop logical shift.";
3278
6956ee35 3279 if (INTVAL (amount) > 0
e4a25868 3280 && INTVAL (amount) < 5)
3281 return "rrum.w\t%2, %0"; /* Two bytes. */
3282
6956ee35 3283 if (INTVAL (amount) > 4
e4a25868 3284 && INTVAL (amount) < 9)
3285 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
3286
3287 /* First we logically shift right by one. Now we know
3288 that the top bit is zero and we can use the arithmetic
3289 right shift instruction to perform the rest of the shift. */
3290 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
3291}
b56a9dbc 3292
3293/* Stop GCC from thinking that it can eliminate (SUBREG:PSI (SI)). */
3294
3295#undef TARGET_CAN_CHANGE_MODE_CLASS
3296#define TARGET_CAN_CHANGE_MODE_CLASS msp430_can_change_mode_class
3297
3298static bool
3299msp430_can_change_mode_class (machine_mode from, machine_mode to, reg_class_t)
3300{
3301 if ((to == PSImode && from == SImode)
3302 || (to == SImode && from == PSImode)
3303 || (to == DImode && from == PSImode)
3304 || (to == PSImode && from == DImode))
3305 return false;
3306 return true;
3307}
e4a25868 3308\f
c1207228 3309#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
3310#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
3311
e4a25868 3312struct gcc_target targetm = TARGET_INITIALIZER;
3313
3314#include "gt-msp430.h"