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