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