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