]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/msp430/msp430.c
gcc/ada/
[thirdparty/gcc.git] / gcc / config / msp430 / msp430.c
1 /* Subroutines used for code generation on TI MSP430 processors.
2 Copyright (C) 2012-2014 Free Software Foundation, Inc.
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
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "tree.h"
26 #include "stor-layout.h"
27 #include "calls.h"
28 #include "rtl.h"
29 #include "regs.h"
30 #include "hard-reg-set.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "output.h"
34 #include "insn-attr.h"
35 #include "flags.h"
36 #include "hashtab.h"
37 #include "hash-set.h"
38 #include "vec.h"
39 #include "machmode.h"
40 #include "input.h"
41 #include "function.h"
42 #include "expr.h"
43 #include "optabs.h"
44 #include "libfuncs.h"
45 #include "recog.h"
46 #include "diagnostic-core.h"
47 #include "toplev.h"
48 #include "reload.h"
49 #include "dominance.h"
50 #include "cfg.h"
51 #include "cfgrtl.h"
52 #include "cfganal.h"
53 #include "lcm.h"
54 #include "cfgbuild.h"
55 #include "cfgcleanup.h"
56 #include "predict.h"
57 #include "basic-block.h"
58 #include "df.h"
59 #include "ggc.h"
60 #include "tm_p.h"
61 #include "debug.h"
62 #include "target.h"
63 #include "target-def.h"
64 #include "langhooks.h"
65 #include "msp430-protos.h"
66 #include "dumpfile.h"
67 #include "opts.h"
68 #include "builtins.h"
69 \f
70
71 static void msp430_compute_frame_info (void);
72
73 \f
74
75 /* Run-time Target Specification. */
76
77 bool msp430x = true;
78
79 struct GTY(()) machine_function
80 {
81 /* If set, the rest of the fields have been computed. */
82 int computed;
83 /* Which registers need to be saved in the pro/epilogue. */
84 int need_to_save [FIRST_PSEUDO_REGISTER];
85
86 /* These fields describe the frame layout... */
87 /* arg pointer */
88 /* 2/4 bytes for saved PC */
89 int framesize_regs;
90 /* frame pointer */
91 int framesize_locals;
92 int framesize_outgoing;
93 /* stack pointer */
94 int framesize;
95
96 /* How much we adjust the stack when returning from an exception
97 handler. */
98 rtx eh_stack_adjust;
99 };
100
101 /* This is our init_machine_status, as set in
102 msp_option_override. */
103 static struct machine_function *
104 msp430_init_machine_status (void)
105 {
106 struct machine_function *m;
107
108 m = ggc_cleared_alloc<machine_function> ();
109
110 return m;
111 }
112
113 #undef TARGET_OPTION_OVERRIDE
114 #define TARGET_OPTION_OVERRIDE msp430_option_override
115
116 static const char * msp430_mcu_names [] =
117 {
118 "msp430afe221", "msp430afe222", "msp430afe223", "msp430afe231",
119 "msp430afe232", "msp430afe233", "msp430afe251", "msp430afe252",
120 "msp430afe253", "msp430c091", "msp430c092", "msp430c111",
121 "msp430c1111", "msp430c112", "msp430c1121", "msp430c1331",
122 "msp430c1351", "msp430c311s", "msp430c312", "msp430c313",
123 "msp430c314", "msp430c315", "msp430c323", "msp430c325",
124 "msp430c336", "msp430c337", "msp430c412", "msp430c413",
125 "msp430e112", "msp430e313", "msp430e315", "msp430e325",
126 "msp430e337", "msp430f110", "msp430f1101", "msp430f1101a",
127 "msp430f1111", "msp430f1111a", "msp430f112", "msp430f1121",
128 "msp430f1121a", "msp430f1122", "msp430f1132", "msp430f122",
129 "msp430f1222", "msp430f123", "msp430f1232", "msp430f133",
130 "msp430f135", "msp430f147", "msp430f1471", "msp430f148",
131 "msp430f1481", "msp430f149", "msp430f1491", "msp430f155",
132 "msp430f156", "msp430f157", "msp430f1610", "msp430f1611",
133 "msp430f1612", "msp430f167", "msp430f168", "msp430f169",
134 "msp430f2001", "msp430f2002", "msp430f2003", "msp430f2011",
135 "msp430f2012", "msp430f2013", "msp430f2101", "msp430f2111",
136 "msp430f2112", "msp430f2121", "msp430f2122", "msp430f2131",
137 "msp430f2132", "msp430f2232", "msp430f2234", "msp430f2252",
138 "msp430f2254", "msp430f2272", "msp430f2274", "msp430f233",
139 "msp430f2330", "msp430f235", "msp430f2350", "msp430f2370",
140 "msp430f2410", "msp430f247", "msp430f2471", "msp430f248",
141 "msp430f2481", "msp430f249", "msp430f2491", "msp430f412",
142 "msp430f413", "msp430f4132", "msp430f415", "msp430f4152",
143 "msp430f417", "msp430f423", "msp430f423a", "msp430f425",
144 "msp430f4250", "msp430f425a", "msp430f4260", "msp430f427",
145 "msp430f4270", "msp430f427a", "msp430f435", "msp430f4351",
146 "msp430f436", "msp430f4361", "msp430f437", "msp430f4371",
147 "msp430f438", "msp430f439", "msp430f447", "msp430f448",
148 "msp430f4481", "msp430f449", "msp430f4491", "msp430f477",
149 "msp430f478", "msp430f4783", "msp430f4784", "msp430f479",
150 "msp430f4793", "msp430f4794", "msp430fe423", "msp430fe4232",
151 "msp430fe423a", "msp430fe4242", "msp430fe425", "msp430fe4252",
152 "msp430fe425a", "msp430fe427", "msp430fe4272", "msp430fe427a",
153 "msp430fg4250", "msp430fg4260", "msp430fg4270", "msp430fg437",
154 "msp430fg438", "msp430fg439", "msp430fg477", "msp430fg478",
155 "msp430fg479", "msp430fw423", "msp430fw425", "msp430fw427",
156 "msp430fw428", "msp430fw429", "msp430g2001", "msp430g2101",
157 "msp430g2102", "msp430g2111", "msp430g2112", "msp430g2113",
158 "msp430g2121", "msp430g2131", "msp430g2132", "msp430g2152",
159 "msp430g2153", "msp430g2201", "msp430g2202", "msp430g2203",
160 "msp430g2210", "msp430g2211", "msp430g2212", "msp430g2213",
161 "msp430g2221", "msp430g2230", "msp430g2231", "msp430g2232",
162 "msp430g2233", "msp430g2252", "msp430g2253", "msp430g2302",
163 "msp430g2303", "msp430g2312", "msp430g2313", "msp430g2332",
164 "msp430g2333", "msp430g2352", "msp430g2353", "msp430g2402",
165 "msp430g2403", "msp430g2412", "msp430g2413", "msp430g2432",
166 "msp430g2433", "msp430g2444", "msp430g2452", "msp430g2453",
167 "msp430g2513", "msp430g2533", "msp430g2544", "msp430g2553",
168 "msp430g2744", "msp430g2755", "msp430g2855", "msp430g2955",
169 "msp430i2020", "msp430i2021", "msp430i2030", "msp430i2031",
170 "msp430i2040", "msp430i2041", "msp430l092", "msp430p112",
171 "msp430p313", "msp430p315", "msp430p315s", "msp430p325",
172 "msp430p337", "msp430tch5e"
173 };
174
175 /* Generate a C preprocessor symbol based upon the MCU selected by the user.
176 If a specific MCU has not been selected then return a generic symbol instead. */
177
178 const char *
179 msp430_mcu_name (void)
180 {
181 if (target_mcu)
182 {
183 unsigned int i;
184 static char mcu_name [64];
185
186 snprintf (mcu_name, sizeof (mcu_name) - 1, "__%s__", target_mcu);
187 for (i = strlen (mcu_name); i--;)
188 mcu_name[i] = TOUPPER (mcu_name[i]);
189 return mcu_name;
190 }
191
192 return msp430x ? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
193 }
194
195 static void
196 msp430_option_override (void)
197 {
198 init_machine_status = msp430_init_machine_status;
199
200 if (target_cpu)
201 {
202 if (strcasecmp (target_cpu, "msp430x") == 0)
203 msp430x = true;
204 else /* target_cpu == "msp430" - already handled by the front end. */
205 msp430x = false;
206 }
207 /* Note - the front end has already ensured at most
208 one of target_cpu and target_mcu will be set. */
209 else if (target_mcu)
210 {
211 int i;
212
213 /* If we are given an MCU name, we assume that it supports 430X.
214 Then we check to see if it is one of the known MCUs that only
215 supports 430. */
216 msp430x = true;
217
218 for (i = ARRAY_SIZE (msp430_mcu_names); i--;)
219 if (strcasecmp (msp430_mcu_names[i], target_mcu) == 0)
220 {
221 msp430x = false;
222 break;
223 }
224 /* It is not an error if we do not match the MCU name. There are
225 hundreds of them. */
226 }
227
228 if (TARGET_LARGE && !msp430x)
229 error ("-mlarge requires a 430X-compatible -mmcu=");
230
231 if (flag_exceptions || flag_non_call_exceptions
232 || flag_unwind_tables || flag_asynchronous_unwind_tables)
233 flag_omit_frame_pointer = false;
234 else
235 flag_omit_frame_pointer = true;
236
237 /* This is a hack to work around a problem with the newlib build
238 mechanism. Newlib always appends CFLAGS to the end of the GCC
239 command line and always sets -O2 in CFLAGS. Thus it is not
240 possible to build newlib with -Os enabled. Until now... */
241 if (TARGET_OPT_SPACE && optimize < 3)
242 optimize_size = 1;
243 }
244
245 #undef TARGET_SCALAR_MODE_SUPPORTED_P
246 #define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
247
248 static bool
249 msp430_scalar_mode_supported_p (machine_mode m)
250 {
251 if (m == PSImode && msp430x)
252 return true;
253 #if 0
254 if (m == TImode)
255 return true;
256 #endif
257 return default_scalar_mode_supported_p (m);
258 }
259
260 \f
261
262 /* Storage Layout */
263
264 #undef TARGET_MS_BITFIELD_LAYOUT_P
265 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
266
267 bool
268 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED)
269 {
270 return false;
271 }
272
273 \f
274
275 /* Register Usage */
276
277 /* Implements HARD_REGNO_NREGS. MSP430X registers can hold a single
278 PSImode value, but not an SImode value. */
279 int
280 msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED,
281 machine_mode mode)
282 {
283 if (mode == PSImode && msp430x)
284 return 1;
285 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
286 / UNITS_PER_WORD);
287 }
288
289 /* Implements HARD_REGNO_NREGS_HAS_PADDING. */
290 int
291 msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED,
292 machine_mode mode)
293 {
294 if (mode == PSImode && msp430x)
295 return 1;
296 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
297 / UNITS_PER_WORD);
298 }
299
300 /* Implements HARD_REGNO_NREGS_WITH_PADDING. */
301 int
302 msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED,
303 machine_mode mode)
304 {
305 if (mode == PSImode)
306 return 2;
307 return msp430_hard_regno_nregs (regno, mode);
308 }
309
310 /* Implements HARD_REGNO_MODE_OK. */
311 int
312 msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED,
313 machine_mode mode)
314 {
315 return regno <= (ARG_POINTER_REGNUM - msp430_hard_regno_nregs (regno, mode));
316 }
317
318 /* Implements MODES_TIEABLE_P. */
319 bool
320 msp430_modes_tieable_p (machine_mode mode1, machine_mode mode2)
321 {
322 if ((mode1 == PSImode || mode2 == SImode)
323 || (mode1 == SImode || mode2 == PSImode))
324 return false;
325
326 return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
327 || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
328 == (GET_MODE_CLASS (mode2) == MODE_FLOAT
329 || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
330 }
331
332 #undef TARGET_FRAME_POINTER_REQUIRED
333 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
334
335 static bool
336 msp430_frame_pointer_required (void)
337 {
338 return false;
339 }
340
341 #undef TARGET_CAN_ELIMINATE
342 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
343
344 static bool
345 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED,
346 const int to_reg ATTRIBUTE_UNUSED)
347 {
348 return true;
349 }
350
351 /* Implements INITIAL_ELIMINATION_OFFSET. */
352 int
353 msp430_initial_elimination_offset (int from, int to)
354 {
355 int rv = 0; /* As if arg to arg. */
356
357 msp430_compute_frame_info ();
358
359 switch (to)
360 {
361 case STACK_POINTER_REGNUM:
362 rv += cfun->machine->framesize_outgoing;
363 rv += cfun->machine->framesize_locals;
364 /* Fall through. */
365 case FRAME_POINTER_REGNUM:
366 rv += cfun->machine->framesize_regs;
367 /* Allow for the saved return address. */
368 rv += (TARGET_LARGE ? 4 : 2);
369 /* NB/ No need to allow for crtl->args.pretend_args_size.
370 GCC does that for us. */
371 break;
372 default:
373 gcc_unreachable ();
374 }
375
376 switch (from)
377 {
378 case FRAME_POINTER_REGNUM:
379 /* Allow for the fall through above. */
380 rv -= (TARGET_LARGE ? 4 : 2);
381 rv -= cfun->machine->framesize_regs;
382 case ARG_POINTER_REGNUM:
383 break;
384 default:
385 gcc_unreachable ();
386 }
387
388 return rv;
389 }
390 \f
391 /* Named Address Space support */
392
393
394 /* Return the appropriate mode for a named address pointer. */
395 #undef TARGET_ADDR_SPACE_POINTER_MODE
396 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
397 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
398 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
399
400 static machine_mode
401 msp430_addr_space_pointer_mode (addr_space_t addrspace)
402 {
403 switch (addrspace)
404 {
405 default:
406 case ADDR_SPACE_GENERIC:
407 return Pmode;
408 case ADDR_SPACE_NEAR:
409 return HImode;
410 case ADDR_SPACE_FAR:
411 return PSImode;
412 }
413 }
414
415 /* Function pointers are stored in unwind_word sized
416 variables, so make sure that unwind_word is big enough. */
417 #undef TARGET_UNWIND_WORD_MODE
418 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
419
420 static machine_mode
421 msp430_unwind_word_mode (void)
422 {
423 return TARGET_LARGE ? PSImode : HImode;
424 }
425
426 /* Determine if one named address space is a subset of another. */
427 #undef TARGET_ADDR_SPACE_SUBSET_P
428 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
429 static bool
430 msp430_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
431 {
432 if (subset == superset)
433 return true;
434 else
435 return (subset != ADDR_SPACE_FAR && superset == ADDR_SPACE_FAR);
436 }
437
438 #undef TARGET_ADDR_SPACE_CONVERT
439 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
440 /* Convert from one address space to another. */
441 static rtx
442 msp430_addr_space_convert (rtx op, tree from_type, tree to_type)
443 {
444 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
445 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
446 rtx result;
447
448 if (to_as != ADDR_SPACE_FAR && from_as == ADDR_SPACE_FAR)
449 {
450 /* This is unpredictable, as we're truncating off usable address
451 bits. */
452
453 if (CONSTANT_P (op))
454 return gen_rtx_CONST (HImode, op);
455
456 result = gen_reg_rtx (HImode);
457 emit_insn (gen_truncpsihi2 (result, op));
458 return result;
459 }
460 else if (to_as == ADDR_SPACE_FAR && from_as != ADDR_SPACE_FAR)
461 {
462 /* This always works. */
463
464 if (CONSTANT_P (op))
465 return gen_rtx_CONST (PSImode, op);
466
467 result = gen_reg_rtx (PSImode);
468 emit_insn (gen_zero_extendhipsi2 (result, op));
469 return result;
470 }
471 else
472 gcc_unreachable ();
473 }
474 \f
475 /* Stack Layout and Calling Conventions. */
476
477 /* For each function, we list the gcc version and the TI version on
478 each line, where we're converting the function names. */
479 static char const * const special_convention_function_names [] =
480 {
481 "__muldi3", "__mspabi_mpyll",
482 "__udivdi3", "__mspabi_divull",
483 "__umoddi3", "__mspabi_remull",
484 "__divdi3", "__mspabi_divlli",
485 "__moddi3", "__mspabi_remlli",
486 "__mspabi_srall",
487 "__mspabi_srlll",
488 "__mspabi_sllll",
489 "__adddf3", "__mspabi_addd",
490 "__subdf3", "__mspabi_subd",
491 "__muldf3", "__mspabi_mpyd",
492 "__divdf3", "__mspabi_divd",
493 "__mspabi_cmpd",
494 NULL
495 };
496
497 /* TRUE if the function passed is a "speical" function. Special
498 functions pass two DImode parameters in registers. */
499 static bool
500 msp430_special_register_convention_p (const char *name)
501 {
502 int i;
503
504 for (i = 0; special_convention_function_names [i]; i++)
505 if (! strcmp (name, special_convention_function_names [i]))
506 return true;
507
508 return false;
509 }
510
511 #undef TARGET_FUNCTION_VALUE_REGNO_P
512 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
513
514 bool
515 msp430_function_value_regno_p (unsigned int regno)
516 {
517 return regno == 12;
518 }
519
520
521 #undef TARGET_FUNCTION_VALUE
522 #define TARGET_FUNCTION_VALUE msp430_function_value
523
524 rtx
525 msp430_function_value (const_tree ret_type,
526 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
527 bool outgoing ATTRIBUTE_UNUSED)
528 {
529 return gen_rtx_REG (TYPE_MODE (ret_type), 12);
530 }
531
532 #undef TARGET_LIBCALL_VALUE
533 #define TARGET_LIBCALL_VALUE msp430_libcall_value
534
535 rtx
536 msp430_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
537 {
538 return gen_rtx_REG (mode, 12);
539 }
540
541 /* Implements INIT_CUMULATIVE_ARGS. */
542 void
543 msp430_init_cumulative_args (CUMULATIVE_ARGS *ca,
544 tree fntype ATTRIBUTE_UNUSED,
545 rtx libname ATTRIBUTE_UNUSED,
546 tree fndecl ATTRIBUTE_UNUSED,
547 int n_named_args ATTRIBUTE_UNUSED)
548 {
549 const char *fname;
550 memset (ca, 0, sizeof(*ca));
551
552 ca->can_split = 1;
553
554 if (fndecl)
555 fname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
556 else if (libname)
557 fname = XSTR (libname, 0);
558 else
559 fname = NULL;
560
561 if (fname && msp430_special_register_convention_p (fname))
562 ca->special_p = 1;
563 }
564
565 /* Helper function for argument passing; this function is the common
566 code that determines where an argument will be passed. */
567 static void
568 msp430_evaluate_arg (cumulative_args_t cap,
569 machine_mode mode,
570 const_tree type ATTRIBUTE_UNUSED,
571 bool named)
572 {
573 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
574 int nregs = GET_MODE_SIZE (mode);
575 int i;
576
577 ca->reg_count = 0;
578 ca->mem_count = 0;
579
580 if (!named)
581 return;
582
583 if (mode == PSImode)
584 nregs = 1;
585 else
586 nregs = (nregs + 1) / 2;
587
588 if (ca->special_p)
589 {
590 /* Function is passed two DImode operands, in R8:R11 and
591 R12:15. */
592 ca->start_reg = 8;
593 ca->reg_count = 4;
594 return;
595 }
596
597 switch (nregs)
598 {
599 case 1:
600 for (i = 0; i < 4; i++)
601 if (! ca->reg_used [i])
602 {
603 ca->reg_count = 1;
604 ca->start_reg = CA_FIRST_REG + i;
605 return;
606 }
607 break;
608 case 2:
609 for (i = 0; i < 3; i++)
610 if (! ca->reg_used [i] && ! ca->reg_used [i + 1])
611 {
612 ca->reg_count = 2;
613 ca->start_reg = CA_FIRST_REG + i;
614 return;
615 }
616 if (! ca->reg_used [3] && ca->can_split)
617 {
618 ca->reg_count = 1;
619 ca->mem_count = 2;
620 ca->start_reg = CA_FIRST_REG + 3;
621 return;
622 }
623 break;
624 case 3:
625 case 4:
626 ca->can_split = 0;
627 if (! ca->reg_used [0]
628 && ! ca->reg_used [1]
629 && ! ca->reg_used [2]
630 && ! ca->reg_used [3])
631 {
632 ca->reg_count = 4;
633 ca->start_reg = CA_FIRST_REG;
634 return;
635 }
636 break;
637 }
638 }
639
640 #undef TARGET_PROMOTE_PROTOTYPES
641 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
642
643 bool
644 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED)
645 {
646 return false;
647 }
648
649 #undef TARGET_FUNCTION_ARG
650 #define TARGET_FUNCTION_ARG msp430_function_arg
651
652 rtx
653 msp430_function_arg (cumulative_args_t cap,
654 machine_mode mode,
655 const_tree type,
656 bool named)
657 {
658 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
659
660 msp430_evaluate_arg (cap, mode, type, named);
661
662 if (ca->reg_count)
663 return gen_rtx_REG (mode, ca->start_reg);
664
665 return 0;
666 }
667
668 #undef TARGET_ARG_PARTIAL_BYTES
669 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
670
671 int
672 msp430_arg_partial_bytes (cumulative_args_t cap,
673 machine_mode mode,
674 tree type,
675 bool named)
676 {
677 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
678
679 msp430_evaluate_arg (cap, mode, type, named);
680
681 if (ca->reg_count && ca->mem_count)
682 return ca->reg_count * UNITS_PER_WORD;
683
684 return 0;
685 }
686
687 #undef TARGET_PASS_BY_REFERENCE
688 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
689
690 static bool
691 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED,
692 machine_mode mode,
693 const_tree type,
694 bool named ATTRIBUTE_UNUSED)
695 {
696 return (mode == BLKmode
697 || (type && TREE_CODE (type) == RECORD_TYPE)
698 || (type && TREE_CODE (type) == UNION_TYPE));
699 }
700
701 #undef TARGET_CALLEE_COPIES
702 #define TARGET_CALLEE_COPIES msp430_callee_copies
703
704 static bool
705 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED,
706 machine_mode mode ATTRIBUTE_UNUSED,
707 const_tree type ATTRIBUTE_UNUSED,
708 bool named ATTRIBUTE_UNUSED)
709 {
710 return true;
711 }
712
713 #undef TARGET_FUNCTION_ARG_ADVANCE
714 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
715
716 void
717 msp430_function_arg_advance (cumulative_args_t cap,
718 machine_mode mode,
719 const_tree type,
720 bool named)
721 {
722 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
723 int i;
724
725 msp430_evaluate_arg (cap, mode, type, named);
726
727 if (ca->start_reg >= CA_FIRST_REG)
728 for (i = 0; i < ca->reg_count; i ++)
729 ca->reg_used [i + ca->start_reg - CA_FIRST_REG] = 1;
730
731 ca->special_p = 0;
732 }
733
734 #undef TARGET_FUNCTION_ARG_BOUNDARY
735 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
736
737 static unsigned int
738 msp430_function_arg_boundary (machine_mode mode, const_tree type)
739 {
740 if (mode == BLKmode
741 && int_size_in_bytes (type) > 1)
742 return 16;
743 if (GET_MODE_BITSIZE (mode) > 8)
744 return 16;
745 return 8;
746 }
747
748 #undef TARGET_RETURN_IN_MEMORY
749 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
750
751 static bool
752 msp430_return_in_memory (const_tree ret_type, const_tree fntype ATTRIBUTE_UNUSED)
753 {
754 machine_mode mode = TYPE_MODE (ret_type);
755
756 if (mode == BLKmode
757 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == RECORD_TYPE)
758 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == UNION_TYPE))
759 return true;
760
761 if (GET_MODE_SIZE (mode) > 8)
762 return true;
763
764 return false;
765 }
766
767 #undef TARGET_GET_RAW_ARG_MODE
768 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
769
770 static machine_mode
771 msp430_get_raw_arg_mode (int regno)
772 {
773 return (regno == ARG_POINTER_REGNUM) ? VOIDmode : Pmode;
774 }
775
776 #undef TARGET_GET_RAW_RESULT_MODE
777 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
778
779 static machine_mode
780 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED)
781 {
782 return Pmode;
783 }
784
785 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
786 #define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
787
788 #include "gimplify.h"
789 #include "gimple-expr.h"
790
791 static tree
792 msp430_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
793 gimple_seq *post_p)
794 {
795 tree addr, t, type_size, rounded_size, valist_tmp;
796 unsigned HOST_WIDE_INT align, boundary;
797 bool indirect;
798
799 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
800 if (indirect)
801 type = build_pointer_type (type);
802
803 align = PARM_BOUNDARY / BITS_PER_UNIT;
804 boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
805
806 /* When we align parameter on stack for caller, if the parameter
807 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
808 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
809 here with caller. */
810 if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
811 boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
812
813 boundary /= BITS_PER_UNIT;
814
815 /* Hoist the valist value into a temporary for the moment. */
816 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
817
818 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
819 requires greater alignment, we must perform dynamic alignment. */
820 if (boundary > align
821 && !integer_zerop (TYPE_SIZE (type)))
822 {
823 /* FIXME: This is where this function diverts from targhooks.c:
824 std_gimplify_va_arg_expr(). It works, but I do not know why... */
825 if (! POINTER_TYPE_P (type))
826 {
827 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
828 fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
829 gimplify_and_add (t, pre_p);
830
831 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
832 fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
833 valist_tmp,
834 build_int_cst (TREE_TYPE (valist), -boundary)));
835 gimplify_and_add (t, pre_p);
836 }
837 }
838 else
839 boundary = align;
840
841 /* If the actual alignment is less than the alignment of the type,
842 adjust the type accordingly so that we don't assume strict alignment
843 when dereferencing the pointer. */
844 boundary *= BITS_PER_UNIT;
845 if (boundary < TYPE_ALIGN (type))
846 {
847 type = build_variant_type_copy (type);
848 TYPE_ALIGN (type) = boundary;
849 }
850
851 /* Compute the rounded size of the type. */
852 type_size = size_in_bytes (type);
853 rounded_size = round_up (type_size, align);
854
855 /* Reduce rounded_size so it's sharable with the postqueue. */
856 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
857
858 /* Get AP. */
859 addr = valist_tmp;
860
861 /* Compute new value for AP. */
862 t = fold_build_pointer_plus (valist_tmp, rounded_size);
863 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
864 gimplify_and_add (t, pre_p);
865
866 addr = fold_convert (build_pointer_type (type), addr);
867
868 if (indirect)
869 addr = build_va_arg_indirect_ref (addr);
870
871 addr = build_va_arg_indirect_ref (addr);
872
873 return addr;
874 }
875 \f
876 /* Addressing Modes */
877
878 #undef TARGET_LEGITIMATE_ADDRESS_P
879 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
880
881 static bool
882 reg_ok_for_addr (rtx r, bool strict)
883 {
884 int rn = REGNO (r);
885
886 if (strict && rn >= FIRST_PSEUDO_REGISTER)
887 rn = reg_renumber [rn];
888 if (strict && 0 <= rn && rn < FIRST_PSEUDO_REGISTER)
889 return true;
890 if (!strict)
891 return true;
892 return false;
893 }
894
895 bool
896 msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
897 rtx x ATTRIBUTE_UNUSED,
898 bool strict ATTRIBUTE_UNUSED)
899 {
900 switch (GET_CODE (x))
901 {
902 case MEM:
903 return false;
904
905 case PLUS:
906 if (REG_P (XEXP (x, 0)))
907 {
908 if (GET_MODE (x) != GET_MODE (XEXP (x, 0)))
909 return false;
910 if (!reg_ok_for_addr (XEXP (x, 0), strict))
911 return false;
912 switch (GET_CODE (XEXP (x, 1)))
913 {
914 case CONST:
915 case SYMBOL_REF:
916 case CONST_INT:
917 return true;
918 default:
919 return false;
920 }
921 }
922 return false;
923
924 case REG:
925 if (!reg_ok_for_addr (x, strict))
926 return false;
927 /* else... */
928 case CONST:
929 case SYMBOL_REF:
930 case CONST_INT:
931 return true;
932
933 default:
934 return false;
935 }
936 }
937
938 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
939 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
940
941 bool
942 msp430_addr_space_legitimate_address_p (machine_mode mode,
943 rtx x,
944 bool strict,
945 addr_space_t as ATTRIBUTE_UNUSED)
946 {
947 return msp430_legitimate_address_p (mode, x, strict);
948 }
949
950 #undef TARGET_ASM_INTEGER
951 #define TARGET_ASM_INTEGER msp430_asm_integer
952 static bool
953 msp430_asm_integer (rtx x, unsigned int size, int aligned_p)
954 {
955 int c = GET_CODE (x);
956
957 if (size == 3 && GET_MODE (x) == PSImode)
958 size = 4;
959
960 switch (size)
961 {
962 case 4:
963 if (c == SYMBOL_REF || c == CONST || c == LABEL_REF || c == CONST_INT)
964 {
965 fprintf (asm_out_file, "\t.long\t");
966 output_addr_const (asm_out_file, x);
967 fputc ('\n', asm_out_file);
968 return true;
969 }
970 break;
971 }
972 return default_assemble_integer (x, size, aligned_p);
973 }
974
975 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
976 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra
977 static bool
978 msp430_asm_output_addr_const_extra (FILE *file, rtx x)
979 {
980 debug_rtx(x);
981 return false;
982 }
983
984 #undef TARGET_LEGITIMATE_CONSTANT_P
985 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
986
987 static bool
988 msp430_legitimate_constant (machine_mode mode, rtx x)
989 {
990 return ! CONST_INT_P (x)
991 || mode != PSImode
992 /* GCC does not know the width of the PSImode, so make
993 sure that it does not try to use a constant value that
994 is out of range. */
995 || (INTVAL (x) < (1 << 20) && INTVAL (x) >= (-1 << 20));
996 }
997
998 \f
999 #undef TARGET_RTX_COSTS
1000 #define TARGET_RTX_COSTS msp430_rtx_costs
1001
1002 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED,
1003 int code,
1004 int outer_code ATTRIBUTE_UNUSED,
1005 int opno ATTRIBUTE_UNUSED,
1006 int * total,
1007 bool speed ATTRIBUTE_UNUSED)
1008 {
1009 switch (code)
1010 {
1011 case SIGN_EXTEND:
1012 if (GET_MODE (x) == SImode && outer_code == SET)
1013 {
1014 *total = COSTS_N_INSNS (4);
1015 return true;
1016 }
1017 break;
1018 case ASHIFT:
1019 case ASHIFTRT:
1020 case LSHIFTRT:
1021 if (!msp430x)
1022 {
1023 *total = COSTS_N_INSNS (100);
1024 return true;
1025 }
1026 break;
1027 }
1028 return false;
1029 }
1030 \f
1031 /* Function Entry and Exit */
1032
1033 /* The MSP430 call frame looks like this:
1034
1035 <higher addresses>
1036 +--------------------+
1037 | |
1038 | Stack Arguments |
1039 | |
1040 +--------------------+ <-- "arg pointer"
1041 | |
1042 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
1043 | |
1044 +--------------------+
1045 | SR if this func has|
1046 | been called via an |
1047 | interrupt. |
1048 +--------------------+ <-- SP before prologue, also AP
1049 | |
1050 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
1051 | |
1052 +--------------------+ <-- "frame pointer"
1053 | |
1054 | Locals |
1055 | |
1056 +--------------------+
1057 | |
1058 | Outgoing Args |
1059 | |
1060 +--------------------+ <-- SP during function
1061 <lower addresses>
1062
1063 */
1064
1065 /* We use this to wrap all emitted insns in the prologue, so they get
1066 the "frame-related" (/f) flag set. */
1067 static rtx
1068 F (rtx x)
1069 {
1070 RTX_FRAME_RELATED_P (x) = 1;
1071 return x;
1072 }
1073
1074 /* This is the one spot that decides if a register is to be saved and
1075 restored in the prologue/epilogue. */
1076 static bool
1077 msp430_preserve_reg_p (int regno)
1078 {
1079 /* PC, SP, SR, and the constant generator. */
1080 if (regno <= 3)
1081 return false;
1082
1083 /* FIXME: add interrupt, EH, etc. */
1084 if (crtl->calls_eh_return)
1085 return true;
1086
1087 /* Shouldn't be more than the above, but just in case... */
1088 if (fixed_regs [regno])
1089 return false;
1090
1091 /* Interrupt handlers save all registers they use, even
1092 ones which are call saved. If they call other functions
1093 then *every* register is saved. */
1094 if (msp430_is_interrupt_func ())
1095 return ! crtl->is_leaf || df_regs_ever_live_p (regno);
1096
1097 if (!call_used_regs [regno]
1098 && df_regs_ever_live_p (regno))
1099 return true;
1100
1101 return false;
1102 }
1103
1104 /* Compute all the frame-related fields in our machine_function
1105 structure. */
1106 static void
1107 msp430_compute_frame_info (void)
1108 {
1109 int i;
1110
1111 cfun->machine->computed = 1;
1112 cfun->machine->framesize_regs = 0;
1113 cfun->machine->framesize_locals = get_frame_size ();
1114 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
1115
1116 for (i = 0; i < ARG_POINTER_REGNUM; i ++)
1117 if (msp430_preserve_reg_p (i))
1118 {
1119 cfun->machine->need_to_save [i] = 1;
1120 cfun->machine->framesize_regs += (TARGET_LARGE ? 4 : 2);
1121 }
1122 else
1123 cfun->machine->need_to_save [i] = 0;
1124
1125 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
1126 cfun->machine->framesize_locals ++;
1127
1128 cfun->machine->framesize = (cfun->machine->framesize_regs
1129 + cfun->machine->framesize_locals
1130 + cfun->machine->framesize_outgoing);
1131 }
1132
1133 static inline bool
1134 is_attr_func (const char * attr)
1135 {
1136 return lookup_attribute (attr, DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE;
1137 }
1138
1139 /* Returns true if the current function has the "interrupt" attribute. */
1140
1141 bool
1142 msp430_is_interrupt_func (void)
1143 {
1144 if (current_function_decl == NULL)
1145 return false;
1146 return is_attr_func ("interrupt");
1147 }
1148
1149 static bool
1150 is_wakeup_func (void)
1151 {
1152 return msp430_is_interrupt_func () && is_attr_func ("wakeup");
1153 }
1154
1155 static inline bool
1156 is_naked_func (void)
1157 {
1158 return is_attr_func ("naked");
1159 }
1160
1161 static inline bool
1162 is_reentrant_func (void)
1163 {
1164 return is_attr_func ("reentrant");
1165 }
1166
1167 static inline bool
1168 is_critical_func (void)
1169 {
1170 return is_attr_func ("critical");
1171 }
1172
1173 #undef TARGET_ASM_FUNCTION_PROLOGUE
1174 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
1175
1176 static void
1177 msp430_start_function (FILE *outfile, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
1178 {
1179 int r, n;
1180
1181 fprintf (outfile, "; start of function\n");
1182
1183 if (DECL_ATTRIBUTES (current_function_decl) != NULL_TREE)
1184 {
1185 fprintf (outfile, "; attributes: ");
1186 if (is_naked_func ())
1187 fprintf (outfile, "naked ");
1188 if (msp430_is_interrupt_func ())
1189 fprintf (outfile, "interrupt ");
1190 if (is_reentrant_func ())
1191 fprintf (outfile, "reentrant ");
1192 if (is_critical_func ())
1193 fprintf (outfile, "critical ");
1194 if (is_wakeup_func ())
1195 fprintf (outfile, "wakeup ");
1196 fprintf (outfile, "\n");
1197 }
1198
1199 fprintf (outfile, "; framesize_regs: %d\n", cfun->machine->framesize_regs);
1200 fprintf (outfile, "; framesize_locals: %d\n", cfun->machine->framesize_locals);
1201 fprintf (outfile, "; framesize_outgoing: %d\n", cfun->machine->framesize_outgoing);
1202 fprintf (outfile, "; framesize: %d\n", cfun->machine->framesize);
1203 fprintf (outfile, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM));
1204 fprintf (outfile, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM));
1205
1206 n = 0;
1207 fprintf (outfile, "; saved regs:");
1208 for (r = 0; r < ARG_POINTER_REGNUM; r++)
1209 if (cfun->machine->need_to_save [r])
1210 {
1211 fprintf (outfile, " %s", reg_names [r]);
1212 n = 1;
1213 }
1214 if (n == 0)
1215 fprintf (outfile, "(none)");
1216 fprintf (outfile, "\n");
1217 }
1218
1219 /* Common code to change the stack pointer. */
1220 static void
1221 increment_stack (HOST_WIDE_INT amount)
1222 {
1223 rtx inc;
1224 rtx sp = stack_pointer_rtx;
1225
1226 if (amount == 0)
1227 return;
1228
1229 if (amount < 0)
1230 {
1231 inc = GEN_INT (- amount);
1232 if (TARGET_LARGE)
1233 F (emit_insn (gen_subpsi3 (sp, sp, inc)));
1234 else
1235 F (emit_insn (gen_subhi3 (sp, sp, inc)));
1236 }
1237 else
1238 {
1239 inc = GEN_INT (amount);
1240 if (TARGET_LARGE)
1241 emit_insn (gen_addpsi3 (sp, sp, inc));
1242 else
1243 emit_insn (gen_addhi3 (sp, sp, inc));
1244 }
1245 }
1246
1247 /* Verify MSP430 specific attributes. */
1248
1249 static tree
1250 msp430_attr (tree * node,
1251 tree name,
1252 tree args,
1253 int flags ATTRIBUTE_UNUSED,
1254 bool * no_add_attrs)
1255 {
1256 gcc_assert (DECL_P (* node));
1257
1258 if (args != NULL)
1259 {
1260 tree value = TREE_VALUE (args);
1261
1262 switch (TREE_CODE (value))
1263 {
1264 case STRING_CST:
1265 if ( strcmp (TREE_STRING_POINTER (value), "reset")
1266 && strcmp (TREE_STRING_POINTER (value), "nmi")
1267 && strcmp (TREE_STRING_POINTER (value), "watchdog"))
1268 /* Allow the attribute to be added - the linker script
1269 being used may still recognise this name. */
1270 warning (OPT_Wattributes,
1271 "unrecognised interrupt vector argument of %qE attribute",
1272 name);
1273 break;
1274
1275 case INTEGER_CST:
1276 if (wi::gtu_p (value, 63))
1277 /* Allow the attribute to be added - the linker script
1278 being used may still recognise this value. */
1279 warning (OPT_Wattributes,
1280 "numeric argument of %qE attribute must be in range 0..63",
1281 name);
1282 break;
1283
1284 default:
1285 warning (OPT_Wattributes,
1286 "argument of %qE attribute is not a string constant or number",
1287 name);
1288 *no_add_attrs = true;
1289 break;
1290 }
1291 }
1292
1293 if (TREE_CODE (* node) != FUNCTION_DECL)
1294 {
1295 warning (OPT_Wattributes,
1296 "%qE attribute only applies to functions",
1297 name);
1298 * no_add_attrs = true;
1299 }
1300
1301 /* FIXME: We ought to check that the interrupt handler
1302 attribute has been applied to a void function. */
1303 /* FIXME: We should check that reentrant and critical
1304 functions are not naked and that critical functions
1305 are not reentrant. */
1306
1307 return NULL_TREE;
1308 }
1309
1310 #undef TARGET_ATTRIBUTE_TABLE
1311 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
1312
1313 /* Table of MSP430-specific attributes. */
1314 const struct attribute_spec msp430_attribute_table[] =
1315 {
1316 /* Name min_len decl_req, fn_type_req, affects_type_identity
1317 max_len, type_req, handler. */
1318 { "interrupt", 0, 1, true, false, false, msp430_attr, false },
1319 { "naked", 0, 0, true, false, false, msp430_attr, false },
1320 { "reentrant", 0, 0, true, false, false, msp430_attr, false },
1321 { "critical", 0, 0, true, false, false, msp430_attr, false },
1322 { "wakeup", 0, 0, true, false, false, msp430_attr, false },
1323 { NULL, 0, 0, false, false, false, NULL, false }
1324 };
1325
1326 void
1327 msp430_start_function (FILE *file, const char *name, tree decl)
1328 {
1329 tree int_attr;
1330
1331 int_attr = lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl));
1332 if (int_attr != NULL_TREE)
1333 {
1334 tree intr_vector = TREE_VALUE (int_attr);
1335
1336 if (intr_vector != NULL_TREE)
1337 {
1338 char buf[101];
1339
1340 intr_vector = TREE_VALUE (intr_vector);
1341
1342 /* The interrupt attribute has a vector value. Turn this into a
1343 section name, switch to that section and put the address of
1344 the current function into that vector slot. Note msp430_attr()
1345 has already verified the vector name for us. */
1346 if (TREE_CODE (intr_vector) == STRING_CST)
1347 sprintf (buf, "__interrupt_vector_%.80s",
1348 TREE_STRING_POINTER (intr_vector));
1349 else /* TREE_CODE (intr_vector) == INTEGER_CST */
1350 sprintf (buf, "__interrupt_vector_%u",
1351 (unsigned int) TREE_INT_CST_LOW (intr_vector));
1352
1353 switch_to_section (get_section (buf, SECTION_CODE, decl));
1354 fputs ("\t.word\t", file);
1355 assemble_name (file, name);
1356 fputc ('\n', file);
1357 fputc ('\t', file);
1358 }
1359 }
1360
1361 switch_to_section (function_section (decl));
1362 ASM_OUTPUT_FUNCTION_LABEL (file, name, decl);
1363 }
1364
1365 static section *
1366 msp430_function_section (tree decl, enum node_frequency freq, bool startup, bool exit)
1367 {
1368 /* In large mode we must make sure that interrupt handlers are put into
1369 low memory as the vector table only accepts 16-bit addresses. */
1370 if (TARGET_LARGE
1371 && lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl)))
1372 return get_section (".lowtext", SECTION_CODE | SECTION_WRITE , decl);
1373
1374 /* Otherwise, use the default function section. */
1375 return default_function_section (decl, freq, startup, exit);
1376 }
1377
1378 #undef TARGET_ASM_FUNCTION_SECTION
1379 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
1380
1381 enum msp430_builtin
1382 {
1383 MSP430_BUILTIN_BIC_SR,
1384 MSP430_BUILTIN_BIS_SR,
1385 MSP430_BUILTIN_DELAY_CYCLES,
1386 MSP430_BUILTIN_max
1387 };
1388
1389 static GTY(()) tree msp430_builtins [(int) MSP430_BUILTIN_max];
1390
1391 static void
1392 msp430_init_builtins (void)
1393 {
1394 tree void_ftype_int = build_function_type_list (void_type_node, integer_type_node, NULL);
1395 tree void_ftype_longlong = build_function_type_list (void_type_node, long_long_integer_type_node, NULL);
1396
1397 msp430_builtins[MSP430_BUILTIN_BIC_SR] =
1398 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int,
1399 MSP430_BUILTIN_BIC_SR, BUILT_IN_MD, NULL, NULL_TREE);
1400
1401 msp430_builtins[MSP430_BUILTIN_BIS_SR] =
1402 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int,
1403 MSP430_BUILTIN_BIS_SR, BUILT_IN_MD, NULL, NULL_TREE);
1404
1405 msp430_builtins[MSP430_BUILTIN_DELAY_CYCLES] =
1406 add_builtin_function ( "__delay_cycles", void_ftype_longlong,
1407 MSP430_BUILTIN_DELAY_CYCLES, BUILT_IN_MD, NULL, NULL_TREE);
1408 }
1409
1410 static tree
1411 msp430_builtin_decl (unsigned code, bool initialize ATTRIBUTE_UNUSED)
1412 {
1413 switch (code)
1414 {
1415 case MSP430_BUILTIN_BIC_SR:
1416 case MSP430_BUILTIN_BIS_SR:
1417 case MSP430_BUILTIN_DELAY_CYCLES:
1418 return msp430_builtins[code];
1419 default:
1420 return error_mark_node;
1421 }
1422 }
1423
1424 /* These constants are really register reads, which are faster than
1425 regular constants. */
1426 static int
1427 cg_magic_constant (HOST_WIDE_INT c)
1428 {
1429 switch (c)
1430 {
1431 case 0xffff:
1432 case -1:
1433 case 0:
1434 case 1:
1435 case 2:
1436 case 4:
1437 case 8:
1438 return 1;
1439 default:
1440 return 0;
1441 }
1442 }
1443
1444 static rtx
1445 msp430_expand_delay_cycles (rtx arg)
1446 {
1447 HOST_WIDE_INT i, c, n;
1448 /* extra cycles for MSP430X instructions */
1449 #define CYCX(M,X) (msp430x ? (X) : (M))
1450
1451 if (GET_CODE (arg) != CONST_INT)
1452 {
1453 error ("__delay_cycles() only takes constant arguments");
1454 return NULL_RTX;
1455 }
1456
1457 c = INTVAL (arg);
1458
1459 if (HOST_BITS_PER_WIDE_INT > 32)
1460 {
1461 if (c < 0)
1462 {
1463 error ("__delay_cycles only takes non-negative cycle counts.");
1464 return NULL_RTX;
1465 }
1466 }
1467
1468 emit_insn (gen_delay_cycles_start (arg));
1469
1470 /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
1471 if (c > 3 * 0xffff + CYCX (7, 10))
1472 {
1473 n = c;
1474 /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
1475 if (c >= 0x10000 * 7 + CYCX (14, 16))
1476 {
1477 i = 0x10000;
1478 c -= CYCX (14, 16) + 7 * 0x10000;
1479 i += c / 4;
1480 c %= 4;
1481 if ((unsigned long long) i > 0xffffffffULL)
1482 {
1483 error ("__delay_cycles is limited to 32-bit loop counts.");
1484 return NULL_RTX;
1485 }
1486 }
1487 else
1488 {
1489 i = (c - CYCX (14, 16)) / 7;
1490 c -= CYCX (14, 16) + i * 7;
1491 }
1492
1493 if (cg_magic_constant (i & 0xffff))
1494 c ++;
1495 if (cg_magic_constant ((i >> 16) & 0xffff))
1496 c ++;
1497
1498 if (msp430x)
1499 emit_insn (gen_delay_cycles_32x (GEN_INT (i), GEN_INT (n - c)));
1500 else
1501 emit_insn (gen_delay_cycles_32 (GEN_INT (i), GEN_INT (n - c)));
1502 }
1503
1504 /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
1505 if (c > 12)
1506 {
1507 n = c;
1508 i = (c - CYCX (7, 10)) / 3;
1509 c -= CYCX (7, 10) + i * 3;
1510
1511 if (cg_magic_constant (i))
1512 c ++;
1513
1514 if (msp430x)
1515 emit_insn (gen_delay_cycles_16x (GEN_INT (i), GEN_INT (n - c)));
1516 else
1517 emit_insn (gen_delay_cycles_16 (GEN_INT (i), GEN_INT (n - c)));
1518 }
1519
1520 while (c > 1)
1521 {
1522 emit_insn (gen_delay_cycles_2 ());
1523 c -= 2;
1524 }
1525
1526 if (c)
1527 {
1528 emit_insn (gen_delay_cycles_1 ());
1529 c -= 1;
1530 }
1531
1532 emit_insn (gen_delay_cycles_end (arg));
1533
1534 return NULL_RTX;
1535 }
1536
1537 static rtx
1538 msp430_expand_builtin (tree exp,
1539 rtx target ATTRIBUTE_UNUSED,
1540 rtx subtarget ATTRIBUTE_UNUSED,
1541 machine_mode mode ATTRIBUTE_UNUSED,
1542 int ignore ATTRIBUTE_UNUSED)
1543 {
1544 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
1545 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
1546 rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
1547
1548 if (fcode == MSP430_BUILTIN_DELAY_CYCLES)
1549 return msp430_expand_delay_cycles (arg1);
1550
1551 if (! msp430_is_interrupt_func ())
1552 {
1553 error ("MSP430 builtin functions only work inside interrupt handlers");
1554 return NULL_RTX;
1555 }
1556
1557 if (! REG_P (arg1) && ! CONSTANT_P (arg1))
1558 arg1 = force_reg (mode, arg1);
1559
1560 switch (fcode)
1561 {
1562 case MSP430_BUILTIN_BIC_SR: emit_insn (gen_bic_SR (arg1)); break;
1563 case MSP430_BUILTIN_BIS_SR: emit_insn (gen_bis_SR (arg1)); break;
1564 default:
1565 internal_error ("bad builtin code");
1566 break;
1567 }
1568 return NULL_RTX;
1569 }
1570
1571 #undef TARGET_INIT_BUILTINS
1572 #define TARGET_INIT_BUILTINS msp430_init_builtins
1573
1574 #undef TARGET_EXPAND_BUILTIN
1575 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
1576
1577 #undef TARGET_BUILTIN_DECL
1578 #define TARGET_BUILTIN_DECL msp430_builtin_decl
1579
1580 void
1581 msp430_expand_prologue (void)
1582 {
1583 int i, j;
1584 int fs;
1585 /* Always use stack_pointer_rtx instead of calling
1586 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
1587 that there is a single rtx representing the stack pointer,
1588 namely stack_pointer_rtx, and uses == to recognize it. */
1589 rtx sp = stack_pointer_rtx;
1590 rtx p;
1591
1592 if (is_naked_func ())
1593 {
1594 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
1595 examines the output of the gen_prologue() function. */
1596 emit_insn (gen_rtx_CLOBBER (VOIDmode, GEN_INT (0)));
1597 return;
1598 }
1599
1600 emit_insn (gen_prologue_start_marker ());
1601
1602 if (is_critical_func ())
1603 {
1604 emit_insn (gen_push_intr_state ());
1605 emit_insn (gen_disable_interrupts ());
1606 }
1607 else if (is_reentrant_func ())
1608 emit_insn (gen_disable_interrupts ());
1609
1610 if (!cfun->machine->computed)
1611 msp430_compute_frame_info ();
1612
1613 if (flag_stack_usage_info)
1614 current_function_static_stack_size = cfun->machine->framesize;
1615
1616 if (crtl->args.pretend_args_size)
1617 {
1618 rtx note;
1619
1620 gcc_assert (crtl->args.pretend_args_size == 2);
1621
1622 p = emit_insn (gen_grow_and_swap ());
1623
1624 /* Document the stack decrement... */
1625 note = F (gen_rtx_SET (Pmode, stack_pointer_rtx,
1626 gen_rtx_MINUS (Pmode, stack_pointer_rtx, GEN_INT (2))));
1627 add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
1628
1629 /* ...and the establishment of a new location for the return address. */
1630 note = F (gen_rtx_SET (Pmode, gen_rtx_MEM (Pmode,
1631 gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-2))),
1632 pc_rtx));
1633 add_reg_note (p, REG_CFA_OFFSET, note);
1634 F (p);
1635 }
1636
1637 for (i = 15; i >= 4; i--)
1638 if (cfun->machine->need_to_save [i])
1639 {
1640 int seq, count;
1641 rtx note;
1642
1643 for (seq = i - 1; seq >= 4 && cfun->machine->need_to_save[seq]; seq --)
1644 ;
1645 count = i - seq;
1646
1647 if (msp430x)
1648 {
1649 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
1650 p = F (emit_insn (gen_pushm (gen_rtx_REG (Pmode, i),
1651 GEN_INT (count))));
1652
1653 note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1));
1654
1655 XVECEXP (note, 0, 0)
1656 = F (gen_rtx_SET (VOIDmode,
1657 stack_pointer_rtx,
1658 gen_rtx_PLUS (Pmode,
1659 stack_pointer_rtx,
1660 GEN_INT (count * (TARGET_LARGE ? -4 : -2)))));
1661
1662 /* *sp-- = R[i-j] */
1663 /* sp+N R10
1664 ...
1665 sp R4 */
1666 for (j = 0; j < count; j ++)
1667 {
1668 rtx addr;
1669 int ofs = (count - j - 1) * (TARGET_LARGE ? 4 : 2);
1670
1671 if (ofs)
1672 addr = gen_rtx_PLUS (Pmode, sp, GEN_INT (ofs));
1673 else
1674 addr = stack_pointer_rtx;
1675
1676 XVECEXP (note, 0, j + 1) =
1677 F (gen_rtx_SET (VOIDmode,
1678 gen_rtx_MEM (Pmode, addr),
1679 gen_rtx_REG (Pmode, i - j)) );
1680 }
1681
1682 add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
1683 i -= count - 1;
1684 }
1685 else
1686 F (emit_insn (gen_push (gen_rtx_REG (Pmode, i))));
1687 }
1688
1689 if (frame_pointer_needed)
1690 F (emit_move_insn (gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM), sp));
1691
1692 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1693
1694 increment_stack (- fs);
1695
1696 emit_insn (gen_prologue_end_marker ());
1697 }
1698
1699 void
1700 msp430_expand_epilogue (int is_eh)
1701 {
1702 int i;
1703 int fs;
1704 int helper_n = 0;
1705
1706 if (is_naked_func ())
1707 {
1708 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
1709 examines the output of the gen_epilogue() function. */
1710 emit_insn (gen_rtx_CLOBBER (VOIDmode, GEN_INT (0)));
1711 return;
1712 }
1713
1714 if (cfun->machine->need_to_save [10])
1715 {
1716 /* Check for a helper function. */
1717 helper_n = 7; /* For when the loop below never sees a match. */
1718 for (i = 9; i >= 4; i--)
1719 if (!cfun->machine->need_to_save [i])
1720 {
1721 helper_n = 10 - i;
1722 for (; i >= 4; i--)
1723 if (cfun->machine->need_to_save [i])
1724 {
1725 helper_n = 0;
1726 break;
1727 }
1728 break;
1729 }
1730 }
1731
1732 emit_insn (gen_epilogue_start_marker ());
1733
1734 if (cfun->decl && strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun->decl)), "main") == 0)
1735 emit_insn (gen_msp430_refsym_need_exit ());
1736
1737 if (is_wakeup_func ())
1738 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
1739 status register current residing on the stack. When this function
1740 executes its RETI instruction the SR will be updated with this saved
1741 value, thus ensuring that the processor is woken up from any low power
1742 state in which it may be residing. */
1743 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
1744
1745 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1746
1747 increment_stack (fs);
1748
1749 if (is_eh)
1750 {
1751 /* We need to add the right "SP" register save just after the
1752 regular ones, so that when we pop it off we're in the EH
1753 return frame, not this one. This overwrites our own return
1754 address, but we're not going to be returning anyway. */
1755 rtx r12 = gen_rtx_REG (Pmode, 12);
1756 rtx (*addPmode)(rtx, rtx, rtx) = TARGET_LARGE ? gen_addpsi3 : gen_addhi3;
1757
1758 /* R12 will hold the new SP. */
1759 i = cfun->machine->framesize_regs;
1760 emit_move_insn (r12, stack_pointer_rtx);
1761 emit_insn (addPmode (r12, r12, EH_RETURN_STACKADJ_RTX));
1762 emit_insn (addPmode (r12, r12, GEN_INT (i)));
1763 emit_move_insn (gen_rtx_MEM (Pmode, plus_constant (Pmode, stack_pointer_rtx, i)), r12);
1764 }
1765
1766 for (i = 4; i <= 15; i++)
1767 if (cfun->machine->need_to_save [i])
1768 {
1769 int seq, count;
1770
1771 for (seq = i + 1; seq <= 15 && cfun->machine->need_to_save[seq]; seq ++)
1772 ;
1773 count = seq - i;
1774
1775 if (msp430x)
1776 {
1777 /* Note: With TARGET_LARGE we still use
1778 POPM as POPX.A is two bytes bigger. */
1779 emit_insn (gen_popm (stack_pointer_rtx, GEN_INT (seq - 1),
1780 GEN_INT (count)));
1781 i += count - 1;
1782 }
1783 else if (i == 11 - helper_n
1784 && ! msp430_is_interrupt_func ()
1785 && ! is_reentrant_func ()
1786 && ! is_critical_func ()
1787 && crtl->args.pretend_args_size == 0
1788 /* Calling the helper takes as many bytes as the POP;RET sequence. */
1789 && helper_n > 1
1790 && !is_eh)
1791 {
1792 emit_insn (gen_epilogue_helper (GEN_INT (helper_n)));
1793 return;
1794 }
1795 else
1796 emit_insn (gen_pop (gen_rtx_REG (Pmode, i)));
1797 }
1798
1799 if (is_eh)
1800 {
1801 /* Also pop SP, which puts us into the EH return frame. Except
1802 that you can't "pop" sp, you have to just load it off the
1803 stack. */
1804 emit_move_insn (stack_pointer_rtx, gen_rtx_MEM (Pmode, stack_pointer_rtx));
1805 }
1806
1807 if (crtl->args.pretend_args_size)
1808 emit_insn (gen_swap_and_shrink ());
1809
1810 if (is_critical_func ())
1811 emit_insn (gen_pop_intr_state ());
1812 else if (is_reentrant_func ())
1813 emit_insn (gen_enable_interrupts ());
1814
1815 emit_jump_insn (gen_msp_return ());
1816 }
1817
1818 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
1819 m32c_emit_eh_epilogue. */
1820 rtx
1821 msp430_eh_return_stackadj_rtx (void)
1822 {
1823 if (!cfun->machine->eh_stack_adjust)
1824 {
1825 rtx sa;
1826
1827 sa = gen_rtx_REG (Pmode, 15);
1828 cfun->machine->eh_stack_adjust = sa;
1829 }
1830 return cfun->machine->eh_stack_adjust;
1831 }
1832
1833 /* This function is called before reload, to "fix" the stack in
1834 preparation for an EH return. */
1835 void
1836 msp430_expand_eh_return (rtx eh_handler)
1837 {
1838 /* These are all Pmode */
1839 rtx ap, sa, ra, tmp;
1840
1841 ap = arg_pointer_rtx;
1842 sa = msp430_eh_return_stackadj_rtx ();
1843 ra = eh_handler;
1844
1845 tmp = ap;
1846 tmp = gen_rtx_PLUS (Pmode, ap, sa);
1847 tmp = plus_constant (Pmode, tmp, TARGET_LARGE ? -4 : -2);
1848 tmp = gen_rtx_MEM (Pmode, tmp);
1849 emit_move_insn (tmp, ra);
1850 }
1851
1852 #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
1853 #define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
1854 void
1855 msp430_init_dwarf_reg_sizes_extra (tree address)
1856 {
1857 int i;
1858 rtx addr = expand_normal (address);
1859 rtx mem = gen_rtx_MEM (BLKmode, addr);
1860
1861 if (!msp430x)
1862 return;
1863
1864 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1865 {
1866 unsigned int dnum = DWARF_FRAME_REGNUM (i);
1867 unsigned int rnum = DWARF2_FRAME_REG_OUT (dnum, 1);
1868
1869 if (rnum < DWARF_FRAME_REGISTERS)
1870 {
1871 HOST_WIDE_INT offset = rnum * GET_MODE_SIZE (QImode);
1872
1873 emit_move_insn (adjust_address (mem, QImode, offset),
1874 gen_int_mode (4, QImode));
1875 }
1876 }
1877 }
1878
1879 /* This is a list of MD patterns that implement fixed-count shifts. */
1880 static struct
1881 {
1882 const char *name;
1883 int count;
1884 int need_430x;
1885 rtx (*genfunc)(rtx,rtx);
1886 }
1887 const_shift_helpers[] =
1888 {
1889 #define CSH(N,C,X,G) { "__mspabi_"N, C, X, gen_##G }
1890
1891 CSH ("slli", 1, 1, slli_1),
1892 CSH ("slll", 1, 1, slll_1),
1893 CSH ("slll", 2, 1, slll_2),
1894
1895 CSH ("srai", 1, 0, srai_1),
1896 CSH ("sral", 1, 0, sral_1),
1897 CSH ("sral", 2, 0, sral_2),
1898
1899 CSH ("srll", 1, 0, srll_1),
1900 CSH ("srll", 2, 1, srll_2x),
1901 { 0, 0, 0, 0 }
1902 #undef CSH
1903 };
1904
1905 /* The MSP430 ABI defines a number of helper functions that should be
1906 used for, for example, 32-bit shifts. This function is called to
1907 emit such a function, using the table above to optimize some
1908 cases. */
1909 void
1910 msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variants)
1911 {
1912 rtx c, f;
1913 char *helper_const = NULL;
1914 int arg2 = 13;
1915 int arg1sz = 1;
1916 machine_mode arg0mode = GET_MODE (operands[0]);
1917 machine_mode arg1mode = GET_MODE (operands[1]);
1918 machine_mode arg2mode = GET_MODE (operands[2]);
1919 int have_430x = msp430x ? 1 : 0;
1920
1921 if (CONST_INT_P (operands[2]))
1922 {
1923 int i;
1924
1925 for (i=0; const_shift_helpers[i].name; i++)
1926 {
1927 if (const_shift_helpers[i].need_430x <= have_430x
1928 && strcmp (helper_name, const_shift_helpers[i].name) == 0
1929 && INTVAL (operands[2]) == const_shift_helpers[i].count)
1930 {
1931 emit_insn (const_shift_helpers[i].genfunc (operands[0], operands[1]));
1932 return;
1933 }
1934 }
1935 }
1936
1937 if (arg1mode == VOIDmode)
1938 arg1mode = arg0mode;
1939 if (arg2mode == VOIDmode)
1940 arg2mode = arg0mode;
1941
1942 if (arg1mode == SImode)
1943 {
1944 arg2 = 14;
1945 arg1sz = 2;
1946 }
1947
1948 if (const_variants
1949 && CONST_INT_P (operands[2])
1950 && INTVAL (operands[2]) >= 1
1951 && INTVAL (operands[2]) <= 15)
1952 {
1953 /* Note that the INTVAL is limited in value and length by the conditional above. */
1954 int len = strlen (helper_name) + 4;
1955 helper_const = (char *) xmalloc (len);
1956 snprintf (helper_const, len, "%s_%d", helper_name, (int) INTVAL (operands[2]));
1957 }
1958
1959 emit_move_insn (gen_rtx_REG (arg1mode, 12),
1960 operands[1]);
1961 if (!helper_const)
1962 emit_move_insn (gen_rtx_REG (arg2mode, arg2),
1963 operands[2]);
1964
1965 c = gen_call_value_internal (gen_rtx_REG (arg0mode, 12),
1966 gen_rtx_SYMBOL_REF (VOIDmode, helper_const ? helper_const : helper_name),
1967 GEN_INT (0));
1968 c = emit_call_insn (c);
1969 RTL_CONST_CALL_P (c) = 1;
1970
1971 f = 0;
1972 use_regs (&f, 12, arg1sz);
1973 if (!helper_const)
1974 use_regs (&f, arg2, 1);
1975 add_function_usage_to (c, f);
1976
1977 emit_move_insn (operands[0],
1978 gen_rtx_REG (arg0mode, 12));
1979 }
1980
1981 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
1982 void
1983 msp430_fixup_compare_operands (machine_mode my_mode, rtx * operands)
1984 {
1985 /* constants we're looking for, not constants which are allowed. */
1986 int const_op_idx = 1;
1987
1988 if (msp430_reversible_cmp_operator (operands[0], VOIDmode))
1989 const_op_idx = 2;
1990
1991 if (GET_CODE (operands[const_op_idx]) != REG
1992 && GET_CODE (operands[const_op_idx]) != MEM)
1993 operands[const_op_idx] = copy_to_mode_reg (my_mode, operands[const_op_idx]);
1994 }
1995
1996 /* Simplify_gen_subreg() doesn't handle memory references the way we
1997 need it to below, so we use this function for when we must get a
1998 valid subreg in a "natural" state. */
1999 rtx
2000 msp430_subreg (machine_mode mode, rtx r, machine_mode omode, int byte)
2001 {
2002 rtx rv;
2003
2004 if (GET_CODE (r) == SUBREG
2005 && SUBREG_BYTE (r) == 0)
2006 {
2007 rtx ireg = SUBREG_REG (r);
2008 machine_mode imode = GET_MODE (ireg);
2009
2010 /* special case for (HI (SI (PSI ...), 0)) */
2011 if (imode == PSImode
2012 && mode == HImode
2013 && byte == 0)
2014 rv = gen_rtx_SUBREG (mode, ireg, byte);
2015 else
2016 rv = simplify_gen_subreg (mode, ireg, imode, byte);
2017 }
2018 else if (GET_CODE (r) == MEM)
2019 rv = adjust_address (r, mode, byte);
2020 else
2021 rv = simplify_gen_subreg (mode, r, omode, byte);
2022
2023 if (!rv)
2024 gcc_unreachable ();
2025
2026 return rv;
2027 }
2028
2029 /* Called by movsi_x to generate the HImode operands. */
2030 void
2031 msp430_split_movsi (rtx *operands)
2032 {
2033 rtx op00, op02, op10, op12;
2034
2035 op00 = msp430_subreg (HImode, operands[0], SImode, 0);
2036 op02 = msp430_subreg (HImode, operands[0], SImode, 2);
2037
2038 if (GET_CODE (operands[1]) == CONST
2039 || GET_CODE (operands[1]) == SYMBOL_REF)
2040 {
2041 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
2042 op10 = gen_rtx_CONST (HImode, op10);
2043 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
2044 op12 = gen_rtx_CONST (HImode, op12);
2045 }
2046 else
2047 {
2048 op10 = msp430_subreg (HImode, operands[1], SImode, 0);
2049 op12 = msp430_subreg (HImode, operands[1], SImode, 2);
2050 }
2051
2052 if (rtx_equal_p (operands[0], operands[1]))
2053 {
2054 operands[2] = op02;
2055 operands[4] = op12;
2056 operands[3] = op00;
2057 operands[5] = op10;
2058 }
2059 else if (rtx_equal_p (op00, op12)
2060 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
2061 || (REG_P (op00) && reg_mentioned_p (op00, op10))
2062 /* Or storing (rN) into mem (rN). */
2063 || (REG_P (op10) && reg_mentioned_p (op10, op00))
2064 )
2065 {
2066 operands[2] = op02;
2067 operands[4] = op12;
2068 operands[3] = op00;
2069 operands[5] = op10;
2070 }
2071 else
2072 {
2073 operands[2] = op00;
2074 operands[4] = op10;
2075 operands[3] = op02;
2076 operands[5] = op12;
2077 }
2078 }
2079
2080 \f
2081 /* The MSPABI specifies the names of various helper functions, many of
2082 which are compatible with GCC's helpers. This table maps the GCC
2083 name to the MSPABI name. */
2084 static const struct
2085 {
2086 char const * const gcc_name;
2087 char const * const ti_name;
2088 }
2089 helper_function_name_mappings [] =
2090 {
2091 /* Floating point to/from integer conversions. */
2092 { "__truncdfsf2", "__mspabi_cvtdf" },
2093 { "__extendsfdf2", "__mspabi_cvtfd" },
2094 { "__fixdfhi", "__mspabi_fixdi" },
2095 { "__fixdfsi", "__mspabi_fixdli" },
2096 { "__fixdfdi", "__mspabi_fixdlli" },
2097 { "__fixunsdfhi", "__mspabi_fixdu" },
2098 { "__fixunsdfsi", "__mspabi_fixdul" },
2099 { "__fixunsdfdi", "__mspabi_fixdull" },
2100 { "__fixsfhi", "__mspabi_fixfi" },
2101 { "__fixsfsi", "__mspabi_fixfli" },
2102 { "__fixsfdi", "__mspabi_fixflli" },
2103 { "__fixunsfhi", "__mspabi_fixfu" },
2104 { "__fixunsfsi", "__mspabi_fixful" },
2105 { "__fixunsfdi", "__mspabi_fixfull" },
2106 { "__floathisf", "__mspabi_fltif" },
2107 { "__floatsisf", "__mspabi_fltlif" },
2108 { "__floatdisf", "__mspabi_fltllif" },
2109 { "__floathidf", "__mspabi_fltid" },
2110 { "__floatsidf", "__mspabi_fltlid" },
2111 { "__floatdidf", "__mspabi_fltllid" },
2112 { "__floatunhisf", "__mspabi_fltuf" },
2113 { "__floatunsisf", "__mspabi_fltulf" },
2114 { "__floatundisf", "__mspabi_fltullf" },
2115 { "__floatunhidf", "__mspabi_fltud" },
2116 { "__floatunsidf", "__mspabi_fltuld" },
2117 { "__floatundidf", "__mspabi_fltulld" },
2118
2119 /* Floating point comparisons. */
2120 /* GCC uses individual functions for each comparison, TI uses one
2121 compare <=> function. */
2122
2123 /* Floating point arithmatic */
2124 { "__adddf3", "__mspabi_addd" },
2125 { "__addsf3", "__mspabi_addf" },
2126 { "__divdf3", "__mspabi_divd" },
2127 { "__divsf3", "__mspabi_divf" },
2128 { "__muldf3", "__mspabi_mpyd" },
2129 { "__mulsf3", "__mspabi_mpyf" },
2130 { "__subdf3", "__mspabi_subd" },
2131 { "__subsf3", "__mspabi_subf" },
2132 /* GCC does not use helper functions for negation */
2133
2134 /* Integer multiply, divide, remainder. */
2135 { "__mulhi3", "__mspabi_mpyi" },
2136 { "__mulsi3", "__mspabi_mpyl" },
2137 { "__muldi3", "__mspabi_mpyll" },
2138 #if 0
2139 /* Clarify signed vs unsigned first. */
2140 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
2141 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
2142 #endif
2143
2144 { "__divhi3", "__mspabi_divi" },
2145 { "__divsi3", "__mspabi_divli" },
2146 { "__divdi3", "__mspabi_divlli" },
2147 { "__udivhi3", "__mspabi_divu" },
2148 { "__udivsi3", "__mspabi_divlu" },
2149 { "__udivdi3", "__mspabi_divllu" },
2150 { "__modhi3", "__mspabi_remi" },
2151 { "__modsi3", "__mspabi_remli" },
2152 { "__moddi3", "__mspabi_remlli" },
2153 { "__umodhi3", "__mspabi_remu" },
2154 { "__umodsi3", "__mspabi_remul" },
2155 { "__umoddi3", "__mspabi_remull" },
2156
2157 /* Bitwise operations. */
2158 /* Rotation - no rotation support yet. */
2159 /* Logical left shift - gcc already does these itself. */
2160 /* Arithmetic left shift - gcc already does these itself. */
2161 /* Arithmetic right shift - gcc already does these itself. */
2162
2163 { NULL, NULL }
2164 };
2165
2166 /* Returns true if the current MCU supports an F5xxx series
2167 hardware multiper. */
2168
2169 bool
2170 msp430_use_f5_series_hwmult (void)
2171 {
2172 static const char * cached_match = NULL;
2173 static bool cached_result;
2174
2175 if (msp430_hwmult_type == F5SERIES)
2176 return true;
2177
2178 if (target_mcu == NULL || msp430_hwmult_type != AUTO)
2179 return false;
2180
2181 if (target_mcu == cached_match)
2182 return cached_result;
2183
2184 cached_match = target_mcu;
2185
2186 if (strncasecmp (target_mcu, "msp430f5", 8) == 0)
2187 return cached_result = true;
2188
2189 static const char * known_f5_mult_mcus [] =
2190 {
2191 "cc430f5123", "cc430f5125", "cc430f5133",
2192 "cc430f5135", "cc430f5137", "cc430f5143",
2193 "cc430f5145", "cc430f5147", "cc430f6125",
2194 "cc430f6126", "cc430f6127", "cc430f6135",
2195 "cc430f6137", "cc430f6143", "cc430f6145",
2196 "cc430f6147", "msp430bt5190", "msp430sl5438a"
2197 };
2198 int i;
2199
2200 for (i = ARRAY_SIZE (known_f5_mult_mcus); i--;)
2201 if (strcasecmp (target_mcu, known_f5_mult_mcus[i]) == 0)
2202 return cached_result = true;
2203
2204 return cached_result = false;
2205 }
2206
2207 /* Returns true if the current MCU has a second generation
2208 32-bit hardware multiplier. */
2209
2210 static bool
2211 use_32bit_hwmult (void)
2212 {
2213 static const char * known_32bit_mult_mcus [] =
2214 {
2215 "msp430f4783", "msp430f4793", "msp430f4784",
2216 "msp430f4794", "msp430f47126", "msp430f47127",
2217 "msp430f47163", "msp430f47173", "msp430f47183",
2218 "msp430f47193", "msp430f47166", "msp430f47176",
2219 "msp430f47186", "msp430f47196", "msp430f47167",
2220 "msp430f47177", "msp430f47187", "msp430f47197"
2221 };
2222 static const char * cached_match = NULL;
2223 static bool cached_result;
2224 int i;
2225
2226 if (msp430_hwmult_type == LARGE)
2227 return true;
2228
2229 if (target_mcu == NULL || msp430_hwmult_type != AUTO)
2230 return false;
2231
2232 if (target_mcu == cached_match)
2233 return cached_result;
2234
2235 cached_match = target_mcu;
2236 for (i = ARRAY_SIZE (known_32bit_mult_mcus); i--;)
2237 if (strcasecmp (target_mcu, known_32bit_mult_mcus[i]) == 0)
2238 return cached_result = true;
2239
2240 return cached_result = false;
2241 }
2242
2243 /* Returns true if the current MCU does not have a
2244 hardware multiplier of any kind. */
2245
2246 static bool
2247 msp430_no_hwmult (void)
2248 {
2249 static const char * known_nomult_mcus [] =
2250 {
2251 "msp430c091", "msp430c092", "msp430c111",
2252 "msp430c1111", "msp430c112", "msp430c1121",
2253 "msp430c1331", "msp430c1351", "msp430c311s",
2254 "msp430c312", "msp430c313", "msp430c314",
2255 "msp430c315", "msp430c323", "msp430c325",
2256 "msp430c412", "msp430c413", "msp430e112",
2257 "msp430e313", "msp430e315", "msp430e325",
2258 "msp430f110", "msp430f1101", "msp430f1101a",
2259 "msp430f1111", "msp430f1111a", "msp430f112",
2260 "msp430f1121", "msp430f1121a", "msp430f1122",
2261 "msp430f1132", "msp430f122", "msp430f1222",
2262 "msp430f123", "msp430f1232", "msp430f133",
2263 "msp430f135", "msp430f155", "msp430f156",
2264 "msp430f157", "msp430f2001", "msp430f2002",
2265 "msp430f2003", "msp430f2011", "msp430f2012",
2266 "msp430f2013", "msp430f2101", "msp430f2111",
2267 "msp430f2112", "msp430f2121", "msp430f2122",
2268 "msp430f2131", "msp430f2132", "msp430f2232",
2269 "msp430f2234", "msp430f2252", "msp430f2254",
2270 "msp430f2272", "msp430f2274", "msp430f412",
2271 "msp430f413", "msp430f4132", "msp430f415",
2272 "msp430f4152", "msp430f417", "msp430f4250",
2273 "msp430f4260", "msp430f4270", "msp430f435",
2274 "msp430f4351", "msp430f436", "msp430f4361",
2275 "msp430f437", "msp430f4371", "msp430f438",
2276 "msp430f439", "msp430f477", "msp430f478",
2277 "msp430f479", "msp430fe423", "msp430fe4232",
2278 "msp430fe423a", "msp430fe4242", "msp430fe425",
2279 "msp430fe4252", "msp430fe425a", "msp430fe427",
2280 "msp430fe4272", "msp430fe427a", "msp430fg4250",
2281 "msp430fg4260", "msp430fg4270", "msp430fg437",
2282 "msp430fg438", "msp430fg439", "msp430fg477",
2283 "msp430fg478", "msp430fg479", "msp430fr2032",
2284 "msp430fr2033", "msp430fr4131", "msp430fr4132",
2285 "msp430fr4133", "msp430fw423", "msp430fw425",
2286 "msp430fw427", "msp430fw428", "msp430fw429",
2287 "msp430g2001", "msp430g2101", "msp430g2102",
2288 "msp430g2111", "msp430g2112", "msp430g2113",
2289 "msp430g2121", "msp430g2131", "msp430g2132",
2290 "msp430g2152", "msp430g2153", "msp430g2201",
2291 "msp430g2202", "msp430g2203", "msp430g2210",
2292 "msp430g2211", "msp430g2212", "msp430g2213",
2293 "msp430g2221", "msp430g2230", "msp430g2231",
2294 "msp430g2232", "msp430g2233", "msp430g2252",
2295 "msp430g2253", "msp430g2302", "msp430g2303",
2296 "msp430g2312", "msp430g2313", "msp430g2332",
2297 "msp430g2333", "msp430g2352", "msp430g2353",
2298 "msp430g2402", "msp430g2403", "msp430g2412",
2299 "msp430g2413", "msp430g2432", "msp430g2433",
2300 "msp430g2444", "msp430g2452", "msp430g2453",
2301 "msp430g2513", "msp430g2533", "msp430g2544",
2302 "msp430g2553", "msp430g2744", "msp430g2755",
2303 "msp430g2855", "msp430g2955", "msp430l092",
2304 "msp430p112", "msp430p313", "msp430p315",
2305 "msp430p315s", "msp430p325", "msp430tch5e"
2306 };
2307 static const char * cached_match = NULL;
2308 static bool cached_result;
2309 int i;
2310
2311 if (msp430_hwmult_type == NONE)
2312 return true;
2313
2314 if (target_mcu == NULL || msp430_hwmult_type != AUTO)
2315 return false;
2316
2317 if (target_mcu == cached_match)
2318 return cached_result;
2319
2320 cached_match = target_mcu;
2321 for (i = ARRAY_SIZE (known_nomult_mcus); i--;)
2322 if (strcasecmp (target_mcu, known_nomult_mcus[i]) == 0)
2323 return cached_result = true;
2324
2325 return cached_result = false;
2326 }
2327
2328 /* This function does the same as the default, but it will replace GCC
2329 function names with the MSPABI-specified ones. */
2330
2331 void
2332 msp430_output_labelref (FILE *file, const char *name)
2333 {
2334 int i;
2335
2336 for (i = 0; helper_function_name_mappings [i].gcc_name; i++)
2337 if (strcmp (helper_function_name_mappings [i].gcc_name, name) == 0)
2338 {
2339 name = helper_function_name_mappings [i].ti_name;
2340 break;
2341 }
2342
2343 /* If we have been given a specific MCU name then we may be
2344 able to make use of its hardware multiply capabilities. */
2345 if (msp430_hwmult_type != NONE)
2346 {
2347 if (strcmp ("__mspabi_mpyi", name) == 0)
2348 {
2349 if (msp430_use_f5_series_hwmult ())
2350 name = "__mulhi2_f5";
2351 else if (! msp430_no_hwmult ())
2352 name = "__mulhi2";
2353 }
2354 else if (strcmp ("__mspabi_mpyl", name) == 0)
2355 {
2356 if (msp430_use_f5_series_hwmult ())
2357 name = "__mulsi2_f5";
2358 else if (use_32bit_hwmult ())
2359 name = "__mulsi2_hw32";
2360 else if (! msp430_no_hwmult ())
2361 name = "__mulsi2";
2362 }
2363 }
2364
2365 fputs (name, file);
2366 }
2367
2368 /* Common code for msp430_print_operand... */
2369
2370 static void
2371 msp430_print_operand_raw (FILE * file, rtx op)
2372 {
2373 HOST_WIDE_INT i;
2374
2375 switch (GET_CODE (op))
2376 {
2377 case REG:
2378 fprintf (file, "%s", reg_names [REGNO (op)]);
2379 break;
2380
2381 case CONST_INT:
2382 i = INTVAL (op);
2383 if (TARGET_ASM_HEX)
2384 fprintf (file, "%#" HOST_WIDE_INT_PRINT "x", i);
2385 else
2386 fprintf (file, "%" HOST_WIDE_INT_PRINT "d", i);
2387 break;
2388
2389 case CONST:
2390 case PLUS:
2391 case MINUS:
2392 case SYMBOL_REF:
2393 case LABEL_REF:
2394 output_addr_const (file, op);
2395 break;
2396
2397 default:
2398 print_rtl (file, op);
2399 break;
2400 }
2401 }
2402
2403 #undef TARGET_PRINT_OPERAND_ADDRESS
2404 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
2405
2406 /* Output to stdio stream FILE the assembler syntax for an
2407 instruction operand that is a memory reference whose address
2408 is ADDR. */
2409
2410 static void
2411 msp430_print_operand_addr (FILE * file, rtx addr)
2412 {
2413 switch (GET_CODE (addr))
2414 {
2415 case PLUS:
2416 msp430_print_operand_raw (file, XEXP (addr, 1));
2417 gcc_assert (REG_P (XEXP (addr, 0)));
2418 fprintf (file, "(%s)", reg_names [REGNO (XEXP (addr, 0))]);
2419 return;
2420
2421 case REG:
2422 fprintf (file, "@");
2423 break;
2424
2425 case CONST:
2426 case CONST_INT:
2427 case SYMBOL_REF:
2428 case LABEL_REF:
2429 fprintf (file, "&");
2430 break;
2431
2432 default:
2433 break;
2434 }
2435
2436 msp430_print_operand_raw (file, addr);
2437 }
2438
2439 #undef TARGET_PRINT_OPERAND
2440 #define TARGET_PRINT_OPERAND msp430_print_operand
2441
2442 /* A low 16-bits of int/lower of register pair
2443 B high 16-bits of int/higher of register pair
2444 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
2445 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
2446 H like %B (for backwards compatibility)
2447 I inverse of value
2448 J an integer without a # prefix
2449 L like %A (for backwards compatibility)
2450 O offset of the top of the stack
2451 Q like X but generates an A postfix
2452 R inverse of condition code, unsigned.
2453 X X instruction postfix in large mode
2454 Y value - 4
2455 Z value - 1
2456 b .B or .W or .A, depending upon the mode
2457 p bit position
2458 r inverse of condition code
2459 x like X but only for pointers. */
2460
2461 static void
2462 msp430_print_operand (FILE * file, rtx op, int letter)
2463 {
2464 rtx addr;
2465
2466 /* We can't use c, n, a, or l. */
2467 switch (letter)
2468 {
2469 case 'Z':
2470 gcc_assert (CONST_INT_P (op));
2471 /* Print the constant value, less one. */
2472 fprintf (file, "#%ld", INTVAL (op) - 1);
2473 return;
2474 case 'Y':
2475 gcc_assert (CONST_INT_P (op));
2476 /* Print the constant value, less four. */
2477 fprintf (file, "#%ld", INTVAL (op) - 4);
2478 return;
2479 case 'I':
2480 if (GET_CODE (op) == CONST_INT)
2481 {
2482 /* Inverse of constants */
2483 int i = INTVAL (op);
2484 fprintf (file, "%d", ~i);
2485 return;
2486 }
2487 op = XEXP (op, 0);
2488 break;
2489 case 'r': /* Conditional jump where the condition is reversed. */
2490 switch (GET_CODE (op))
2491 {
2492 case EQ: fprintf (file, "NE"); break;
2493 case NE: fprintf (file, "EQ"); break;
2494 case GEU: fprintf (file, "LO"); break;
2495 case LTU: fprintf (file, "HS"); break;
2496 case GE: fprintf (file, "L"); break;
2497 case LT: fprintf (file, "GE"); break;
2498 /* Assume these have reversed operands. */
2499 case GTU: fprintf (file, "HS"); break;
2500 case LEU: fprintf (file, "LO"); break;
2501 case GT: fprintf (file, "GE"); break;
2502 case LE: fprintf (file, "L"); break;
2503 default:
2504 msp430_print_operand_raw (file, op);
2505 break;
2506 }
2507 return;
2508 case 'R': /* Conditional jump where the operands are reversed. */
2509 switch (GET_CODE (op))
2510 {
2511 case GTU: fprintf (file, "LO"); break;
2512 case LEU: fprintf (file, "HS"); break;
2513 case GT: fprintf (file, "L"); break;
2514 case LE: fprintf (file, "GE"); break;
2515 default:
2516 msp430_print_operand_raw (file, op);
2517 break;
2518 }
2519 return;
2520 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
2521 gcc_assert (CONST_INT_P (op));
2522 fprintf (file, "#%d", 1 << INTVAL (op));
2523 return;
2524 case 'b':
2525 switch (GET_MODE (op))
2526 {
2527 case QImode: fprintf (file, ".B"); return;
2528 case HImode: fprintf (file, ".W"); return;
2529 case PSImode: fprintf (file, ".A"); return;
2530 case SImode: fprintf (file, ".A"); return;
2531 default:
2532 return;
2533 }
2534 case 'A':
2535 case 'L': /* Low half. */
2536 switch (GET_CODE (op))
2537 {
2538 case MEM:
2539 op = adjust_address (op, Pmode, 0);
2540 break;
2541 case REG:
2542 break;
2543 case CONST_INT:
2544 op = GEN_INT (INTVAL (op) & 0xffff);
2545 letter = 0;
2546 break;
2547 default:
2548 /* If you get here, figure out a test case :-) */
2549 gcc_unreachable ();
2550 }
2551 break;
2552 case 'B':
2553 case 'H': /* high half */
2554 switch (GET_CODE (op))
2555 {
2556 case MEM:
2557 op = adjust_address (op, Pmode, 2);
2558 break;
2559 case REG:
2560 op = gen_rtx_REG (Pmode, REGNO (op) + 1);
2561 break;
2562 case CONST_INT:
2563 op = GEN_INT (INTVAL (op) >> 16);
2564 letter = 0;
2565 break;
2566 default:
2567 /* If you get here, figure out a test case :-) */
2568 gcc_unreachable ();
2569 }
2570 break;
2571 case 'C':
2572 switch (GET_CODE (op))
2573 {
2574 case MEM:
2575 op = adjust_address (op, Pmode, 3);
2576 break;
2577 case REG:
2578 op = gen_rtx_REG (Pmode, REGNO (op) + 2);
2579 break;
2580 case CONST_INT:
2581 op = GEN_INT ((long long) INTVAL (op) >> 32);
2582 letter = 0;
2583 break;
2584 default:
2585 /* If you get here, figure out a test case :-) */
2586 gcc_unreachable ();
2587 }
2588 break;
2589 case 'D':
2590 switch (GET_CODE (op))
2591 {
2592 case MEM:
2593 op = adjust_address (op, Pmode, 4);
2594 break;
2595 case REG:
2596 op = gen_rtx_REG (Pmode, REGNO (op) + 3);
2597 break;
2598 case CONST_INT:
2599 op = GEN_INT ((long long) INTVAL (op) >> 48);
2600 letter = 0;
2601 break;
2602 default:
2603 /* If you get here, figure out a test case :-) */
2604 gcc_unreachable ();
2605 }
2606 break;
2607
2608 case 'X':
2609 /* This is used to turn, for example, an ADD opcode into an ADDX
2610 opcode when we're using 20-bit addresses. */
2611 if (TARGET_LARGE || GET_MODE (op) == PSImode)
2612 fprintf (file, "X");
2613 /* We don't care which operand we use, but we want 'X' in the MD
2614 file, so we do it this way. */
2615 return;
2616
2617 case 'x':
2618 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
2619 if (GET_MODE (op) == PSImode)
2620 fprintf (file, "X");
2621 return;
2622
2623 case 'Q':
2624 /* Likewise, for BR -> BRA. */
2625 if (TARGET_LARGE)
2626 fprintf (file, "A");
2627 return;
2628
2629 case 'O':
2630 /* Computes the offset to the top of the stack for the current frame.
2631 This has to be done here rather than in, say, msp430_expand_builtin()
2632 because builtins are expanded before the frame layout is determined. */
2633 fprintf (file, "%d",
2634 msp430_initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM)
2635 - (TARGET_LARGE ? 4 : 2));
2636 return;
2637
2638 case 'J':
2639 gcc_assert (GET_CODE (op) == CONST_INT);
2640 case 0:
2641 break;
2642 default:
2643 output_operand_lossage ("invalid operand prefix");
2644 return;
2645 }
2646
2647 switch (GET_CODE (op))
2648 {
2649 case REG:
2650 msp430_print_operand_raw (file, op);
2651 break;
2652
2653 case MEM:
2654 addr = XEXP (op, 0);
2655 msp430_print_operand_addr (file, addr);
2656 break;
2657
2658 case CONST:
2659 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTRACT)
2660 {
2661 op = XEXP (op, 0);
2662 switch (INTVAL (XEXP (op, 2)))
2663 {
2664 case 0:
2665 fprintf (file, "#lo (");
2666 msp430_print_operand_raw (file, XEXP (op, 0));
2667 fprintf (file, ")");
2668 break;
2669
2670 case 16:
2671 fprintf (file, "#hi (");
2672 msp430_print_operand_raw (file, XEXP (op, 0));
2673 fprintf (file, ")");
2674 break;
2675
2676 default:
2677 output_operand_lossage ("invalid zero extract");
2678 break;
2679 }
2680 break;
2681 }
2682 /* Fall through. */
2683 case CONST_INT:
2684 case SYMBOL_REF:
2685 case LABEL_REF:
2686 if (letter == 0)
2687 fprintf (file, "#");
2688 msp430_print_operand_raw (file, op);
2689 break;
2690
2691 case EQ: fprintf (file, "EQ"); break;
2692 case NE: fprintf (file, "NE"); break;
2693 case GEU: fprintf (file, "HS"); break;
2694 case LTU: fprintf (file, "LO"); break;
2695 case GE: fprintf (file, "GE"); break;
2696 case LT: fprintf (file, "L"); break;
2697
2698 default:
2699 print_rtl (file, op);
2700 break;
2701 }
2702 }
2703
2704 \f
2705 /* Frame stuff. */
2706
2707 rtx
2708 msp430_return_addr_rtx (int count)
2709 {
2710 int ra_size;
2711 if (count)
2712 return NULL_RTX;
2713
2714 ra_size = TARGET_LARGE ? 4 : 2;
2715 if (crtl->args.pretend_args_size)
2716 ra_size += 2;
2717
2718 return gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, arg_pointer_rtx, GEN_INT (- ra_size)));
2719 }
2720
2721 rtx
2722 msp430_incoming_return_addr_rtx (void)
2723 {
2724 return gen_rtx_MEM (Pmode, stack_pointer_rtx);
2725 }
2726 \f
2727 /* Instruction generation stuff. */
2728
2729 /* Generate a sequence of instructions to sign-extend an HI
2730 value into an SI value. Handles the tricky case where
2731 we are overwriting the destination. */
2732
2733 const char *
2734 msp430x_extendhisi (rtx * operands)
2735 {
2736 if (REGNO (operands[0]) == REGNO (operands[1]))
2737 /* Low word of dest == source word. */
2738 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
2739
2740 if (! msp430x)
2741 /* Note: This sequence is approximately the same length as invoking a helper
2742 function to perform the sign-extension, as in:
2743
2744 MOV.W %1, %L0
2745 MOV.W %1, r12
2746 CALL __mspabi_srai_15
2747 MOV.W r12, %H0
2748
2749 but this version does not involve any function calls or using argument
2750 registers, so it reduces register pressure. */
2751 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
2752
2753 if (REGNO (operands[0]) + 1 == REGNO (operands[1]))
2754 /* High word of dest == source word. */
2755 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
2756
2757 /* No overlap between dest and source. */
2758 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
2759 }
2760
2761 /* Likewise for logical right shifts. */
2762 const char *
2763 msp430x_logical_shift_right (rtx amount)
2764 {
2765 /* The MSP430X's logical right shift instruction - RRUM - does
2766 not use an extension word, so we cannot encode a repeat count.
2767 Try various alternatives to work around this. If the count
2768 is in a register we are stuck, hence the assert. */
2769 gcc_assert (CONST_INT_P (amount));
2770
2771 if (INTVAL (amount) <= 0
2772 || INTVAL (amount) >= 16)
2773 return "# nop logical shift.";
2774
2775 if (INTVAL (amount) > 0
2776 && INTVAL (amount) < 5)
2777 return "rrum.w\t%2, %0"; /* Two bytes. */
2778
2779 if (INTVAL (amount) > 4
2780 && INTVAL (amount) < 9)
2781 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
2782
2783 /* First we logically shift right by one. Now we know
2784 that the top bit is zero and we can use the arithmetic
2785 right shift instruction to perform the rest of the shift. */
2786 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
2787 }
2788 \f
2789 struct gcc_target targetm = TARGET_INITIALIZER;
2790
2791 #include "gt-msp430.h"