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