]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/rx/rx.c
685a261967e7bed48fdb6488b91b30a52f9627b2
[thirdparty/gcc.git] / gcc / config / rx / rx.c
1 /* Subroutines used for code generation on Renesas RX processors.
2 Copyright (C) 2008, 2009, 2010, 2011 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 /* To Do:
22
23 * Re-enable memory-to-memory copies and fix up reload. */
24
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "tree.h"
30 #include "rtl.h"
31 #include "regs.h"
32 #include "hard-reg-set.h"
33 #include "insn-config.h"
34 #include "conditions.h"
35 #include "output.h"
36 #include "insn-attr.h"
37 #include "flags.h"
38 #include "function.h"
39 #include "expr.h"
40 #include "optabs.h"
41 #include "libfuncs.h"
42 #include "recog.h"
43 #include "diagnostic-core.h"
44 #include "toplev.h"
45 #include "reload.h"
46 #include "df.h"
47 #include "ggc.h"
48 #include "tm_p.h"
49 #include "debug.h"
50 #include "target.h"
51 #include "target-def.h"
52 #include "langhooks.h"
53 #include "opts.h"
54 \f
55 static void rx_print_operand (FILE *, rtx, int);
56
57 #define CC_FLAG_S (1 << 0)
58 #define CC_FLAG_Z (1 << 1)
59 #define CC_FLAG_O (1 << 2)
60 #define CC_FLAG_C (1 << 3)
61 #define CC_FLAG_FP (1 << 4) /* Fake, to differentiate CC_Fmode. */
62
63 static unsigned int flags_from_mode (enum machine_mode mode);
64 static unsigned int flags_from_code (enum rtx_code code);
65 \f
66 /* Return true if OP is a reference to an object in a small data area. */
67
68 static bool
69 rx_small_data_operand (rtx op)
70 {
71 if (rx_small_data_limit == 0)
72 return false;
73
74 if (GET_CODE (op) == SYMBOL_REF)
75 return SYMBOL_REF_SMALL_P (op);
76
77 return false;
78 }
79
80 static bool
81 rx_is_legitimate_address (enum machine_mode mode, rtx x,
82 bool strict ATTRIBUTE_UNUSED)
83 {
84 if (RTX_OK_FOR_BASE (x, strict))
85 /* Register Indirect. */
86 return true;
87
88 if ((GET_MODE_SIZE (mode) == 4
89 || GET_MODE_SIZE (mode) == 2
90 || GET_MODE_SIZE (mode) == 1)
91 && (GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC))
92 /* Pre-decrement Register Indirect or
93 Post-increment Register Indirect. */
94 return RTX_OK_FOR_BASE (XEXP (x, 0), strict);
95
96 if (GET_CODE (x) == PLUS)
97 {
98 rtx arg1 = XEXP (x, 0);
99 rtx arg2 = XEXP (x, 1);
100 rtx index = NULL_RTX;
101
102 if (REG_P (arg1) && RTX_OK_FOR_BASE (arg1, strict))
103 index = arg2;
104 else if (REG_P (arg2) && RTX_OK_FOR_BASE (arg2, strict))
105 index = arg1;
106 else
107 return false;
108
109 switch (GET_CODE (index))
110 {
111 case CONST_INT:
112 {
113 /* Register Relative: REG + INT.
114 Only positive, mode-aligned, mode-sized
115 displacements are allowed. */
116 HOST_WIDE_INT val = INTVAL (index);
117 int factor;
118
119 if (val < 0)
120 return false;
121
122 switch (GET_MODE_SIZE (mode))
123 {
124 default:
125 case 4: factor = 4; break;
126 case 2: factor = 2; break;
127 case 1: factor = 1; break;
128 }
129
130 if (val > (65535 * factor))
131 return false;
132 return (val % factor) == 0;
133 }
134
135 case REG:
136 /* Unscaled Indexed Register Indirect: REG + REG
137 Size has to be "QI", REG has to be valid. */
138 return GET_MODE_SIZE (mode) == 1 && RTX_OK_FOR_BASE (index, strict);
139
140 case MULT:
141 {
142 /* Scaled Indexed Register Indirect: REG + (REG * FACTOR)
143 Factor has to equal the mode size, REG has to be valid. */
144 rtx factor;
145
146 factor = XEXP (index, 1);
147 index = XEXP (index, 0);
148
149 return REG_P (index)
150 && RTX_OK_FOR_BASE (index, strict)
151 && CONST_INT_P (factor)
152 && GET_MODE_SIZE (mode) == INTVAL (factor);
153 }
154
155 default:
156 return false;
157 }
158 }
159
160 /* Small data area accesses turn into register relative offsets. */
161 return rx_small_data_operand (x);
162 }
163
164 /* Returns TRUE for simple memory addreses, ie ones
165 that do not involve register indirect addressing
166 or pre/post increment/decrement. */
167
168 bool
169 rx_is_restricted_memory_address (rtx mem, enum machine_mode mode)
170 {
171 if (! rx_is_legitimate_address
172 (mode, mem, reload_in_progress || reload_completed))
173 return false;
174
175 switch (GET_CODE (mem))
176 {
177 case REG:
178 /* Simple memory addresses are OK. */
179 return true;
180
181 case PRE_DEC:
182 case POST_INC:
183 return false;
184
185 case PLUS:
186 {
187 rtx base, index;
188
189 /* Only allow REG+INT addressing. */
190 base = XEXP (mem, 0);
191 index = XEXP (mem, 1);
192
193 if (! RX_REG_P (base) || ! CONST_INT_P (index))
194 return false;
195
196 return IN_RANGE (INTVAL (index), 0, (0x10000 * GET_MODE_SIZE (mode)) - 1);
197 }
198
199 case SYMBOL_REF:
200 /* Can happen when small data is being supported.
201 Assume that it will be resolved into GP+INT. */
202 return true;
203
204 default:
205 gcc_unreachable ();
206 }
207 }
208
209 /* Implement TARGET_MODE_DEPENDENT_ADDRESS_P. */
210
211 static bool
212 rx_mode_dependent_address_p (const_rtx addr)
213 {
214 if (GET_CODE (addr) == CONST)
215 addr = XEXP (addr, 0);
216
217 switch (GET_CODE (addr))
218 {
219 /* --REG and REG++ only work in SImode. */
220 case PRE_DEC:
221 case POST_INC:
222 return true;
223
224 case MINUS:
225 case PLUS:
226 if (! REG_P (XEXP (addr, 0)))
227 return true;
228
229 addr = XEXP (addr, 1);
230
231 switch (GET_CODE (addr))
232 {
233 case REG:
234 /* REG+REG only works in SImode. */
235 return true;
236
237 case CONST_INT:
238 /* REG+INT is only mode independent if INT is a
239 multiple of 4, positive and will fit into 8-bits. */
240 if (((INTVAL (addr) & 3) == 0)
241 && IN_RANGE (INTVAL (addr), 4, 252))
242 return false;
243 return true;
244
245 case SYMBOL_REF:
246 case LABEL_REF:
247 return true;
248
249 case MULT:
250 gcc_assert (REG_P (XEXP (addr, 0)));
251 gcc_assert (CONST_INT_P (XEXP (addr, 1)));
252 /* REG+REG*SCALE is always mode dependent. */
253 return true;
254
255 default:
256 /* Not recognized, so treat as mode dependent. */
257 return true;
258 }
259
260 case CONST_INT:
261 case SYMBOL_REF:
262 case LABEL_REF:
263 case REG:
264 /* These are all mode independent. */
265 return false;
266
267 default:
268 /* Everything else is unrecognized,
269 so treat as mode dependent. */
270 return true;
271 }
272 }
273 \f
274 /* A C compound statement to output to stdio stream FILE the
275 assembler syntax for an instruction operand that is a memory
276 reference whose address is ADDR. */
277
278 static void
279 rx_print_operand_address (FILE * file, rtx addr)
280 {
281 switch (GET_CODE (addr))
282 {
283 case REG:
284 fprintf (file, "[");
285 rx_print_operand (file, addr, 0);
286 fprintf (file, "]");
287 break;
288
289 case PRE_DEC:
290 fprintf (file, "[-");
291 rx_print_operand (file, XEXP (addr, 0), 0);
292 fprintf (file, "]");
293 break;
294
295 case POST_INC:
296 fprintf (file, "[");
297 rx_print_operand (file, XEXP (addr, 0), 0);
298 fprintf (file, "+]");
299 break;
300
301 case PLUS:
302 {
303 rtx arg1 = XEXP (addr, 0);
304 rtx arg2 = XEXP (addr, 1);
305 rtx base, index;
306
307 if (REG_P (arg1) && RTX_OK_FOR_BASE (arg1, true))
308 base = arg1, index = arg2;
309 else if (REG_P (arg2) && RTX_OK_FOR_BASE (arg2, true))
310 base = arg2, index = arg1;
311 else
312 {
313 rx_print_operand (file, arg1, 0);
314 fprintf (file, " + ");
315 rx_print_operand (file, arg2, 0);
316 break;
317 }
318
319 if (REG_P (index) || GET_CODE (index) == MULT)
320 {
321 fprintf (file, "[");
322 rx_print_operand (file, index, 'A');
323 fprintf (file, ",");
324 }
325 else /* GET_CODE (index) == CONST_INT */
326 {
327 rx_print_operand (file, index, 'A');
328 fprintf (file, "[");
329 }
330 rx_print_operand (file, base, 0);
331 fprintf (file, "]");
332 break;
333 }
334
335 case CONST:
336 if (GET_CODE (XEXP (addr, 0)) == UNSPEC)
337 {
338 addr = XEXP (addr, 0);
339 gcc_assert (XINT (addr, 1) == UNSPEC_CONST);
340
341 addr = XVECEXP (addr, 0, 0);
342 gcc_assert (CONST_INT_P (addr));
343 }
344 /* Fall through. */
345 case LABEL_REF:
346 case SYMBOL_REF:
347 fprintf (file, "#");
348
349 default:
350 output_addr_const (file, addr);
351 break;
352 }
353 }
354
355 static void
356 rx_print_integer (FILE * file, HOST_WIDE_INT val)
357 {
358 if (IN_RANGE (val, -64, 64))
359 fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
360 else
361 fprintf (file,
362 TARGET_AS100_SYNTAX
363 ? "0%" HOST_WIDE_INT_PRINT "xH" : HOST_WIDE_INT_PRINT_HEX,
364 val);
365 }
366
367 static bool
368 rx_assemble_integer (rtx x, unsigned int size, int is_aligned)
369 {
370 const char * op = integer_asm_op (size, is_aligned);
371
372 if (! CONST_INT_P (x))
373 return default_assemble_integer (x, size, is_aligned);
374
375 if (op == NULL)
376 return false;
377 fputs (op, asm_out_file);
378
379 rx_print_integer (asm_out_file, INTVAL (x));
380 fputc ('\n', asm_out_file);
381 return true;
382 }
383
384
385 /* Handles the insertion of a single operand into the assembler output.
386 The %<letter> directives supported are:
387
388 %A Print an operand without a leading # character.
389 %B Print an integer comparison name.
390 %C Print a control register name.
391 %F Print a condition code flag name.
392 %H Print high part of a DImode register, integer or address.
393 %L Print low part of a DImode register, integer or address.
394 %N Print the negation of the immediate value.
395 %Q If the operand is a MEM, then correctly generate
396 register indirect or register relative addressing.
397 %R Like %Q but for zero-extending loads. */
398
399 static void
400 rx_print_operand (FILE * file, rtx op, int letter)
401 {
402 bool unsigned_load = false;
403
404 switch (letter)
405 {
406 case 'A':
407 /* Print an operand without a leading #. */
408 if (MEM_P (op))
409 op = XEXP (op, 0);
410
411 switch (GET_CODE (op))
412 {
413 case LABEL_REF:
414 case SYMBOL_REF:
415 output_addr_const (file, op);
416 break;
417 case CONST_INT:
418 fprintf (file, "%ld", (long) INTVAL (op));
419 break;
420 default:
421 rx_print_operand (file, op, 0);
422 break;
423 }
424 break;
425
426 case 'B':
427 {
428 enum rtx_code code = GET_CODE (op);
429 enum machine_mode mode = GET_MODE (XEXP (op, 0));
430 const char *ret;
431
432 if (mode == CC_Fmode)
433 {
434 /* C flag is undefined, and O flag carries unordered. None of the
435 branch combinations that include O use it helpfully. */
436 switch (code)
437 {
438 case ORDERED:
439 ret = "no";
440 break;
441 case UNORDERED:
442 ret = "o";
443 break;
444 case LT:
445 ret = "n";
446 break;
447 case GE:
448 ret = "pz";
449 break;
450 case EQ:
451 ret = "eq";
452 break;
453 case NE:
454 ret = "ne";
455 break;
456 default:
457 gcc_unreachable ();
458 }
459 }
460 else
461 {
462 unsigned int flags = flags_from_mode (mode);
463
464 switch (code)
465 {
466 case LT:
467 ret = (flags & CC_FLAG_O ? "lt" : "n");
468 break;
469 case GE:
470 ret = (flags & CC_FLAG_O ? "ge" : "pz");
471 break;
472 case GT:
473 ret = "gt";
474 break;
475 case LE:
476 ret = "le";
477 break;
478 case GEU:
479 ret = "geu";
480 break;
481 case LTU:
482 ret = "ltu";
483 break;
484 case GTU:
485 ret = "gtu";
486 break;
487 case LEU:
488 ret = "leu";
489 break;
490 case EQ:
491 ret = "eq";
492 break;
493 case NE:
494 ret = "ne";
495 break;
496 default:
497 gcc_unreachable ();
498 }
499 gcc_checking_assert ((flags_from_code (code) & ~flags) == 0);
500 }
501 fputs (ret, file);
502 break;
503 }
504
505 case 'C':
506 gcc_assert (CONST_INT_P (op));
507 switch (INTVAL (op))
508 {
509 case 0: fprintf (file, "psw"); break;
510 case 2: fprintf (file, "usp"); break;
511 case 3: fprintf (file, "fpsw"); break;
512 case 4: fprintf (file, "cpen"); break;
513 case 8: fprintf (file, "bpsw"); break;
514 case 9: fprintf (file, "bpc"); break;
515 case 0xa: fprintf (file, "isp"); break;
516 case 0xb: fprintf (file, "fintv"); break;
517 case 0xc: fprintf (file, "intb"); break;
518 default:
519 warning (0, "unreocgnized control register number: %d - using 'psw'",
520 (int) INTVAL (op));
521 fprintf (file, "psw");
522 break;
523 }
524 break;
525
526 case 'F':
527 gcc_assert (CONST_INT_P (op));
528 switch (INTVAL (op))
529 {
530 case 0: case 'c': case 'C': fprintf (file, "C"); break;
531 case 1: case 'z': case 'Z': fprintf (file, "Z"); break;
532 case 2: case 's': case 'S': fprintf (file, "S"); break;
533 case 3: case 'o': case 'O': fprintf (file, "O"); break;
534 case 8: case 'i': case 'I': fprintf (file, "I"); break;
535 case 9: case 'u': case 'U': fprintf (file, "U"); break;
536 default:
537 gcc_unreachable ();
538 }
539 break;
540
541 case 'H':
542 switch (GET_CODE (op))
543 {
544 case REG:
545 fprintf (file, "%s", reg_names [REGNO (op) + (WORDS_BIG_ENDIAN ? 0 : 1)]);
546 break;
547 case CONST_INT:
548 {
549 HOST_WIDE_INT v = INTVAL (op);
550
551 fprintf (file, "#");
552 /* Trickery to avoid problems with shifting 32 bits at a time. */
553 v = v >> 16;
554 v = v >> 16;
555 rx_print_integer (file, v);
556 break;
557 }
558 case CONST_DOUBLE:
559 fprintf (file, "#");
560 rx_print_integer (file, CONST_DOUBLE_HIGH (op));
561 break;
562 case MEM:
563 if (! WORDS_BIG_ENDIAN)
564 op = adjust_address (op, SImode, 4);
565 output_address (XEXP (op, 0));
566 break;
567 default:
568 gcc_unreachable ();
569 }
570 break;
571
572 case 'L':
573 switch (GET_CODE (op))
574 {
575 case REG:
576 fprintf (file, "%s", reg_names [REGNO (op) + (WORDS_BIG_ENDIAN ? 1 : 0)]);
577 break;
578 case CONST_INT:
579 fprintf (file, "#");
580 rx_print_integer (file, INTVAL (op) & 0xffffffff);
581 break;
582 case CONST_DOUBLE:
583 fprintf (file, "#");
584 rx_print_integer (file, CONST_DOUBLE_LOW (op));
585 break;
586 case MEM:
587 if (WORDS_BIG_ENDIAN)
588 op = adjust_address (op, SImode, 4);
589 output_address (XEXP (op, 0));
590 break;
591 default:
592 gcc_unreachable ();
593 }
594 break;
595
596 case 'N':
597 gcc_assert (CONST_INT_P (op));
598 fprintf (file, "#");
599 rx_print_integer (file, - INTVAL (op));
600 break;
601
602 case 'R':
603 gcc_assert (GET_MODE_SIZE (GET_MODE (op)) < 4);
604 unsigned_load = true;
605 /* Fall through. */
606 case 'Q':
607 if (MEM_P (op))
608 {
609 HOST_WIDE_INT offset;
610 rtx mem = op;
611
612 op = XEXP (op, 0);
613
614 if (REG_P (op))
615 offset = 0;
616 else if (GET_CODE (op) == PLUS)
617 {
618 rtx displacement;
619
620 if (REG_P (XEXP (op, 0)))
621 {
622 displacement = XEXP (op, 1);
623 op = XEXP (op, 0);
624 }
625 else
626 {
627 displacement = XEXP (op, 0);
628 op = XEXP (op, 1);
629 gcc_assert (REG_P (op));
630 }
631
632 gcc_assert (CONST_INT_P (displacement));
633 offset = INTVAL (displacement);
634 gcc_assert (offset >= 0);
635
636 fprintf (file, "%ld", offset);
637 }
638 else
639 gcc_unreachable ();
640
641 fprintf (file, "[");
642 rx_print_operand (file, op, 0);
643 fprintf (file, "].");
644
645 switch (GET_MODE_SIZE (GET_MODE (mem)))
646 {
647 case 1:
648 gcc_assert (offset <= 65535 * 1);
649 fprintf (file, unsigned_load ? "UB" : "B");
650 break;
651 case 2:
652 gcc_assert (offset % 2 == 0);
653 gcc_assert (offset <= 65535 * 2);
654 fprintf (file, unsigned_load ? "UW" : "W");
655 break;
656 case 4:
657 gcc_assert (offset % 4 == 0);
658 gcc_assert (offset <= 65535 * 4);
659 fprintf (file, "L");
660 break;
661 default:
662 gcc_unreachable ();
663 }
664 break;
665 }
666
667 /* Fall through. */
668
669 default:
670 switch (GET_CODE (op))
671 {
672 case MULT:
673 /* Should be the scaled part of an
674 indexed register indirect address. */
675 {
676 rtx base = XEXP (op, 0);
677 rtx index = XEXP (op, 1);
678
679 /* Check for a swaped index register and scaling factor.
680 Not sure if this can happen, but be prepared to handle it. */
681 if (CONST_INT_P (base) && REG_P (index))
682 {
683 rtx tmp = base;
684 base = index;
685 index = tmp;
686 }
687
688 gcc_assert (REG_P (base));
689 gcc_assert (REGNO (base) < FIRST_PSEUDO_REGISTER);
690 gcc_assert (CONST_INT_P (index));
691 /* Do not try to verify the value of the scalar as it is based
692 on the mode of the MEM not the mode of the MULT. (Which
693 will always be SImode). */
694 fprintf (file, "%s", reg_names [REGNO (base)]);
695 break;
696 }
697
698 case MEM:
699 output_address (XEXP (op, 0));
700 break;
701
702 case PLUS:
703 output_address (op);
704 break;
705
706 case REG:
707 gcc_assert (REGNO (op) < FIRST_PSEUDO_REGISTER);
708 fprintf (file, "%s", reg_names [REGNO (op)]);
709 break;
710
711 case SUBREG:
712 gcc_assert (subreg_regno (op) < FIRST_PSEUDO_REGISTER);
713 fprintf (file, "%s", reg_names [subreg_regno (op)]);
714 break;
715
716 /* This will only be single precision.... */
717 case CONST_DOUBLE:
718 {
719 unsigned long val;
720 REAL_VALUE_TYPE rv;
721
722 REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
723 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
724 fprintf (file, TARGET_AS100_SYNTAX ? "#0%lxH" : "#0x%lx", val);
725 break;
726 }
727
728 case CONST_INT:
729 fprintf (file, "#");
730 rx_print_integer (file, INTVAL (op));
731 break;
732
733 case SYMBOL_REF:
734 case CONST:
735 case LABEL_REF:
736 case CODE_LABEL:
737 case UNSPEC:
738 rx_print_operand_address (file, op);
739 break;
740
741 default:
742 gcc_unreachable ();
743 }
744 break;
745 }
746 }
747
748 /* Returns an assembler template for a move instruction. */
749
750 char *
751 rx_gen_move_template (rtx * operands, bool is_movu)
752 {
753 static char out_template [64];
754 const char * extension = TARGET_AS100_SYNTAX ? ".L" : "";
755 const char * src_template;
756 const char * dst_template;
757 rtx dest = operands[0];
758 rtx src = operands[1];
759
760 /* Decide which extension, if any, should be given to the move instruction. */
761 switch (CONST_INT_P (src) ? GET_MODE (dest) : GET_MODE (src))
762 {
763 case QImode:
764 /* The .B extension is not valid when
765 loading an immediate into a register. */
766 if (! REG_P (dest) || ! CONST_INT_P (src))
767 extension = ".B";
768 break;
769 case HImode:
770 if (! REG_P (dest) || ! CONST_INT_P (src))
771 /* The .W extension is not valid when
772 loading an immediate into a register. */
773 extension = ".W";
774 break;
775 case SFmode:
776 case SImode:
777 extension = ".L";
778 break;
779 case VOIDmode:
780 /* This mode is used by constants. */
781 break;
782 default:
783 debug_rtx (src);
784 gcc_unreachable ();
785 }
786
787 if (MEM_P (src) && rx_small_data_operand (XEXP (src, 0)))
788 src_template = "%%gp(%A1)[r13]";
789 else
790 src_template = "%1";
791
792 if (MEM_P (dest) && rx_small_data_operand (XEXP (dest, 0)))
793 dst_template = "%%gp(%A0)[r13]";
794 else
795 dst_template = "%0";
796
797 sprintf (out_template, "%s%s\t%s, %s", is_movu ? "movu" : "mov",
798 extension, src_template, dst_template);
799 return out_template;
800 }
801 \f
802 /* Return VALUE rounded up to the next ALIGNMENT boundary. */
803
804 static inline unsigned int
805 rx_round_up (unsigned int value, unsigned int alignment)
806 {
807 alignment -= 1;
808 return (value + alignment) & (~ alignment);
809 }
810
811 /* Return the number of bytes in the argument registers
812 occupied by an argument of type TYPE and mode MODE. */
813
814 static unsigned int
815 rx_function_arg_size (enum machine_mode mode, const_tree type)
816 {
817 unsigned int num_bytes;
818
819 num_bytes = (mode == BLKmode)
820 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
821 return rx_round_up (num_bytes, UNITS_PER_WORD);
822 }
823
824 #define NUM_ARG_REGS 4
825 #define MAX_NUM_ARG_BYTES (NUM_ARG_REGS * UNITS_PER_WORD)
826
827 /* Return an RTL expression describing the register holding a function
828 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
829 be passed on the stack. CUM describes the previous parameters to the
830 function and NAMED is false if the parameter is part of a variable
831 parameter list, or the last named parameter before the start of a
832 variable parameter list. */
833
834 static rtx
835 rx_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode,
836 const_tree type, bool named)
837 {
838 unsigned int next_reg;
839 unsigned int bytes_so_far = *cum;
840 unsigned int size;
841 unsigned int rounded_size;
842
843 /* An exploded version of rx_function_arg_size. */
844 size = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
845 /* If the size is not known it cannot be passed in registers. */
846 if (size < 1)
847 return NULL_RTX;
848
849 rounded_size = rx_round_up (size, UNITS_PER_WORD);
850
851 /* Don't pass this arg via registers if there
852 are insufficient registers to hold all of it. */
853 if (rounded_size + bytes_so_far > MAX_NUM_ARG_BYTES)
854 return NULL_RTX;
855
856 /* Unnamed arguments and the last named argument in a
857 variadic function are always passed on the stack. */
858 if (!named)
859 return NULL_RTX;
860
861 /* Structures must occupy an exact number of registers,
862 otherwise they are passed on the stack. */
863 if ((type == NULL || AGGREGATE_TYPE_P (type))
864 && (size % UNITS_PER_WORD) != 0)
865 return NULL_RTX;
866
867 next_reg = (bytes_so_far / UNITS_PER_WORD) + 1;
868
869 return gen_rtx_REG (mode, next_reg);
870 }
871
872 static void
873 rx_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode,
874 const_tree type, bool named ATTRIBUTE_UNUSED)
875 {
876 *cum += rx_function_arg_size (mode, type);
877 }
878
879 static unsigned int
880 rx_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
881 const_tree type ATTRIBUTE_UNUSED)
882 {
883 return 32;
884 }
885
886 /* Return an RTL describing where a function return value of type RET_TYPE
887 is held. */
888
889 static rtx
890 rx_function_value (const_tree ret_type,
891 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
892 bool outgoing ATTRIBUTE_UNUSED)
893 {
894 enum machine_mode mode = TYPE_MODE (ret_type);
895
896 /* RX ABI specifies that small integer types are
897 promoted to int when returned by a function. */
898 if (GET_MODE_SIZE (mode) > 0
899 && GET_MODE_SIZE (mode) < 4
900 && ! COMPLEX_MODE_P (mode)
901 )
902 return gen_rtx_REG (SImode, FUNC_RETURN_REGNUM);
903
904 return gen_rtx_REG (mode, FUNC_RETURN_REGNUM);
905 }
906
907 /* TARGET_PROMOTE_FUNCTION_MODE must behave in the same way with
908 regard to function returns as does TARGET_FUNCTION_VALUE. */
909
910 static enum machine_mode
911 rx_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
912 enum machine_mode mode,
913 int * punsignedp ATTRIBUTE_UNUSED,
914 const_tree funtype ATTRIBUTE_UNUSED,
915 int for_return)
916 {
917 if (for_return != 1
918 || GET_MODE_SIZE (mode) >= 4
919 || COMPLEX_MODE_P (mode)
920 || GET_MODE_SIZE (mode) < 1)
921 return mode;
922
923 return SImode;
924 }
925
926 static bool
927 rx_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
928 {
929 HOST_WIDE_INT size;
930
931 if (TYPE_MODE (type) != BLKmode
932 && ! AGGREGATE_TYPE_P (type))
933 return false;
934
935 size = int_size_in_bytes (type);
936 /* Large structs and those whose size is not an
937 exact multiple of 4 are returned in memory. */
938 return size < 1
939 || size > 16
940 || (size % UNITS_PER_WORD) != 0;
941 }
942
943 static rtx
944 rx_struct_value_rtx (tree fndecl ATTRIBUTE_UNUSED,
945 int incoming ATTRIBUTE_UNUSED)
946 {
947 return gen_rtx_REG (Pmode, STRUCT_VAL_REGNUM);
948 }
949
950 static bool
951 rx_return_in_msb (const_tree valtype)
952 {
953 return TARGET_BIG_ENDIAN_DATA
954 && (AGGREGATE_TYPE_P (valtype) || TREE_CODE (valtype) == COMPLEX_TYPE);
955 }
956
957 /* Returns true if the provided function has the specified attribute. */
958
959 static inline bool
960 has_func_attr (const_tree decl, const char * func_attr)
961 {
962 if (decl == NULL_TREE)
963 decl = current_function_decl;
964
965 return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
966 }
967
968 /* Returns true if the provided function has the "fast_interrupt" attribute. */
969
970 static inline bool
971 is_fast_interrupt_func (const_tree decl)
972 {
973 return has_func_attr (decl, "fast_interrupt");
974 }
975
976 /* Returns true if the provided function has the "interrupt" attribute. */
977
978 static inline bool
979 is_interrupt_func (const_tree decl)
980 {
981 return has_func_attr (decl, "interrupt");
982 }
983
984 /* Returns true if the provided function has the "naked" attribute. */
985
986 static inline bool
987 is_naked_func (const_tree decl)
988 {
989 return has_func_attr (decl, "naked");
990 }
991 \f
992 static bool use_fixed_regs = false;
993
994 static void
995 rx_conditional_register_usage (void)
996 {
997 static bool using_fixed_regs = false;
998
999 if (rx_small_data_limit > 0)
1000 fixed_regs[GP_BASE_REGNUM] = call_used_regs [GP_BASE_REGNUM] = 1;
1001
1002 if (use_fixed_regs != using_fixed_regs)
1003 {
1004 static char saved_fixed_regs[FIRST_PSEUDO_REGISTER];
1005 static char saved_call_used_regs[FIRST_PSEUDO_REGISTER];
1006
1007 if (use_fixed_regs)
1008 {
1009 unsigned int r;
1010
1011 memcpy (saved_fixed_regs, fixed_regs, sizeof fixed_regs);
1012 memcpy (saved_call_used_regs, call_used_regs, sizeof call_used_regs);
1013
1014 /* This is for fast interrupt handlers. Any register in
1015 the range r10 to r13 (inclusive) that is currently
1016 marked as fixed is now a viable, call-used register. */
1017 for (r = 10; r <= 13; r++)
1018 if (fixed_regs[r])
1019 {
1020 fixed_regs[r] = 0;
1021 call_used_regs[r] = 1;
1022 }
1023
1024 /* Mark r7 as fixed. This is just a hack to avoid
1025 altering the reg_alloc_order array so that the newly
1026 freed r10-r13 registers are the preferred registers. */
1027 fixed_regs[7] = call_used_regs[7] = 1;
1028 }
1029 else
1030 {
1031 /* Restore the normal register masks. */
1032 memcpy (fixed_regs, saved_fixed_regs, sizeof fixed_regs);
1033 memcpy (call_used_regs, saved_call_used_regs, sizeof call_used_regs);
1034 }
1035
1036 using_fixed_regs = use_fixed_regs;
1037 }
1038 }
1039
1040 /* Perform any actions necessary before starting to compile FNDECL.
1041 For the RX we use this to make sure that we have the correct
1042 set of register masks selected. If FNDECL is NULL then we are
1043 compiling top level things. */
1044
1045 static void
1046 rx_set_current_function (tree fndecl)
1047 {
1048 /* Remember the last target of rx_set_current_function. */
1049 static tree rx_previous_fndecl;
1050 bool prev_was_fast_interrupt;
1051 bool current_is_fast_interrupt;
1052
1053 /* Only change the context if the function changes. This hook is called
1054 several times in the course of compiling a function, and we don't want
1055 to slow things down too much or call target_reinit when it isn't safe. */
1056 if (fndecl == rx_previous_fndecl)
1057 return;
1058
1059 prev_was_fast_interrupt
1060 = rx_previous_fndecl
1061 ? is_fast_interrupt_func (rx_previous_fndecl) : false;
1062
1063 current_is_fast_interrupt
1064 = fndecl ? is_fast_interrupt_func (fndecl) : false;
1065
1066 if (prev_was_fast_interrupt != current_is_fast_interrupt)
1067 {
1068 use_fixed_regs = current_is_fast_interrupt;
1069 target_reinit ();
1070 }
1071
1072 rx_previous_fndecl = fndecl;
1073 }
1074 \f
1075 /* Typical stack layout should looks like this after the function's prologue:
1076
1077 | |
1078 -- ^
1079 | | \ |
1080 | | arguments saved | Increasing
1081 | | on the stack | addresses
1082 PARENT arg pointer -> | | /
1083 -------------------------- ---- -------------------
1084 CHILD |ret | return address
1085 --
1086 | | \
1087 | | call saved
1088 | | registers
1089 | | /
1090 --
1091 | | \
1092 | | local
1093 | | variables
1094 frame pointer -> | | /
1095 --
1096 | | \
1097 | | outgoing | Decreasing
1098 | | arguments | addresses
1099 current stack pointer -> | | / |
1100 -------------------------- ---- ------------------ V
1101 | | */
1102
1103 static unsigned int
1104 bit_count (unsigned int x)
1105 {
1106 const unsigned int m1 = 0x55555555;
1107 const unsigned int m2 = 0x33333333;
1108 const unsigned int m4 = 0x0f0f0f0f;
1109
1110 x -= (x >> 1) & m1;
1111 x = (x & m2) + ((x >> 2) & m2);
1112 x = (x + (x >> 4)) & m4;
1113 x += x >> 8;
1114
1115 return (x + (x >> 16)) & 0x3f;
1116 }
1117
1118 #define MUST_SAVE_ACC_REGISTER \
1119 (TARGET_SAVE_ACC_REGISTER \
1120 && (is_interrupt_func (NULL_TREE) \
1121 || is_fast_interrupt_func (NULL_TREE)))
1122
1123 /* Returns either the lowest numbered and highest numbered registers that
1124 occupy the call-saved area of the stack frame, if the registers are
1125 stored as a contiguous block, or else a bitmask of the individual
1126 registers if they are stored piecemeal.
1127
1128 Also computes the size of the frame and the size of the outgoing
1129 arguments block (in bytes). */
1130
1131 static void
1132 rx_get_stack_layout (unsigned int * lowest,
1133 unsigned int * highest,
1134 unsigned int * register_mask,
1135 unsigned int * frame_size,
1136 unsigned int * stack_size)
1137 {
1138 unsigned int reg;
1139 unsigned int low;
1140 unsigned int high;
1141 unsigned int fixed_reg = 0;
1142 unsigned int save_mask;
1143 unsigned int pushed_mask;
1144 unsigned int unneeded_pushes;
1145
1146 if (is_naked_func (NULL_TREE))
1147 {
1148 /* Naked functions do not create their own stack frame.
1149 Instead the programmer must do that for us. */
1150 * lowest = 0;
1151 * highest = 0;
1152 * register_mask = 0;
1153 * frame_size = 0;
1154 * stack_size = 0;
1155 return;
1156 }
1157
1158 for (save_mask = high = low = 0, reg = 1; reg < CC_REGNUM; reg++)
1159 {
1160 if ((df_regs_ever_live_p (reg)
1161 /* Always save all call clobbered registers inside non-leaf
1162 interrupt handlers, even if they are not live - they may
1163 be used in (non-interrupt aware) routines called from this one. */
1164 || (call_used_regs[reg]
1165 && is_interrupt_func (NULL_TREE)
1166 && ! current_function_is_leaf))
1167 && (! call_used_regs[reg]
1168 /* Even call clobbered registered must
1169 be pushed inside interrupt handlers. */
1170 || is_interrupt_func (NULL_TREE)
1171 /* Likewise for fast interrupt handlers, except registers r10 -
1172 r13. These are normally call-saved, but may have been set
1173 to call-used by rx_conditional_register_usage. If so then
1174 they can be used in the fast interrupt handler without
1175 saving them on the stack. */
1176 || (is_fast_interrupt_func (NULL_TREE)
1177 && ! IN_RANGE (reg, 10, 13))))
1178 {
1179 if (low == 0)
1180 low = reg;
1181 high = reg;
1182
1183 save_mask |= 1 << reg;
1184 }
1185
1186 /* Remember if we see a fixed register
1187 after having found the low register. */
1188 if (low != 0 && fixed_reg == 0 && fixed_regs [reg])
1189 fixed_reg = reg;
1190 }
1191
1192 /* If we have to save the accumulator register, make sure
1193 that at least two registers are pushed into the frame. */
1194 if (MUST_SAVE_ACC_REGISTER
1195 && bit_count (save_mask) < 2)
1196 {
1197 save_mask |= (1 << 13) | (1 << 14);
1198 if (low == 0)
1199 low = 13;
1200 if (high == 0 || low == high)
1201 high = low + 1;
1202 }
1203
1204 /* Decide if it would be faster fill in the call-saved area of the stack
1205 frame using multiple PUSH instructions instead of a single PUSHM
1206 instruction.
1207
1208 SAVE_MASK is a bitmask of the registers that must be stored in the
1209 call-save area. PUSHED_MASK is a bitmask of the registers that would
1210 be pushed into the area if we used a PUSHM instruction. UNNEEDED_PUSHES
1211 is a bitmask of those registers in pushed_mask that are not in
1212 save_mask.
1213
1214 We use a simple heuristic that says that it is better to use
1215 multiple PUSH instructions if the number of unnecessary pushes is
1216 greater than the number of necessary pushes.
1217
1218 We also use multiple PUSH instructions if there are any fixed registers
1219 between LOW and HIGH. The only way that this can happen is if the user
1220 has specified --fixed-<reg-name> on the command line and in such
1221 circumstances we do not want to touch the fixed registers at all.
1222
1223 FIXME: Is it worth improving this heuristic ? */
1224 pushed_mask = (-1 << low) & ~(-1 << (high + 1));
1225 unneeded_pushes = (pushed_mask & (~ save_mask)) & pushed_mask;
1226
1227 if ((fixed_reg && fixed_reg <= high)
1228 || (optimize_function_for_speed_p (cfun)
1229 && bit_count (save_mask) < bit_count (unneeded_pushes)))
1230 {
1231 /* Use multiple pushes. */
1232 * lowest = 0;
1233 * highest = 0;
1234 * register_mask = save_mask;
1235 }
1236 else
1237 {
1238 /* Use one push multiple instruction. */
1239 * lowest = low;
1240 * highest = high;
1241 * register_mask = 0;
1242 }
1243
1244 * frame_size = rx_round_up
1245 (get_frame_size (), STACK_BOUNDARY / BITS_PER_UNIT);
1246
1247 if (crtl->args.size > 0)
1248 * frame_size += rx_round_up
1249 (crtl->args.size, STACK_BOUNDARY / BITS_PER_UNIT);
1250
1251 * stack_size = rx_round_up
1252 (crtl->outgoing_args_size, STACK_BOUNDARY / BITS_PER_UNIT);
1253 }
1254
1255 /* Generate a PUSHM instruction that matches the given operands. */
1256
1257 void
1258 rx_emit_stack_pushm (rtx * operands)
1259 {
1260 HOST_WIDE_INT last_reg;
1261 rtx first_push;
1262
1263 gcc_assert (CONST_INT_P (operands[0]));
1264 last_reg = (INTVAL (operands[0]) / UNITS_PER_WORD) - 1;
1265
1266 gcc_assert (GET_CODE (operands[1]) == PARALLEL);
1267 first_push = XVECEXP (operands[1], 0, 1);
1268 gcc_assert (SET_P (first_push));
1269 first_push = SET_SRC (first_push);
1270 gcc_assert (REG_P (first_push));
1271
1272 asm_fprintf (asm_out_file, "\tpushm\t%s-%s\n",
1273 reg_names [REGNO (first_push) - last_reg],
1274 reg_names [REGNO (first_push)]);
1275 }
1276
1277 /* Generate a PARALLEL that will pass the rx_store_multiple_vector predicate. */
1278
1279 static rtx
1280 gen_rx_store_vector (unsigned int low, unsigned int high)
1281 {
1282 unsigned int i;
1283 unsigned int count = (high - low) + 2;
1284 rtx vector;
1285
1286 vector = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
1287
1288 XVECEXP (vector, 0, 0) =
1289 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
1290 gen_rtx_MINUS (SImode, stack_pointer_rtx,
1291 GEN_INT ((count - 1) * UNITS_PER_WORD)));
1292
1293 for (i = 0; i < count - 1; i++)
1294 XVECEXP (vector, 0, i + 1) =
1295 gen_rtx_SET (VOIDmode,
1296 gen_rtx_MEM (SImode,
1297 gen_rtx_MINUS (SImode, stack_pointer_rtx,
1298 GEN_INT ((i + 1) * UNITS_PER_WORD))),
1299 gen_rtx_REG (SImode, high - i));
1300 return vector;
1301 }
1302
1303 /* Mark INSN as being frame related. If it is a PARALLEL
1304 then mark each element as being frame related as well. */
1305
1306 static void
1307 mark_frame_related (rtx insn)
1308 {
1309 RTX_FRAME_RELATED_P (insn) = 1;
1310 insn = PATTERN (insn);
1311
1312 if (GET_CODE (insn) == PARALLEL)
1313 {
1314 unsigned int i;
1315
1316 for (i = 0; i < (unsigned) XVECLEN (insn, 0); i++)
1317 RTX_FRAME_RELATED_P (XVECEXP (insn, 0, i)) = 1;
1318 }
1319 }
1320
1321 static bool
1322 ok_for_max_constant (HOST_WIDE_INT val)
1323 {
1324 if (rx_max_constant_size == 0 || rx_max_constant_size == 4)
1325 /* If there is no constraint on the size of constants
1326 used as operands, then any value is legitimate. */
1327 return true;
1328
1329 /* rx_max_constant_size specifies the maximum number
1330 of bytes that can be used to hold a signed value. */
1331 return IN_RANGE (val, (-1 << (rx_max_constant_size * 8)),
1332 ( 1 << (rx_max_constant_size * 8)));
1333 }
1334
1335 /* Generate an ADD of SRC plus VAL into DEST.
1336 Handles the case where VAL is too big for max_constant_value.
1337 Sets FRAME_RELATED_P on the insn if IS_FRAME_RELATED is true. */
1338
1339 static void
1340 gen_safe_add (rtx dest, rtx src, rtx val, bool is_frame_related)
1341 {
1342 rtx insn;
1343
1344 if (val == NULL_RTX || INTVAL (val) == 0)
1345 {
1346 gcc_assert (dest != src);
1347
1348 insn = emit_move_insn (dest, src);
1349 }
1350 else if (ok_for_max_constant (INTVAL (val)))
1351 insn = emit_insn (gen_addsi3 (dest, src, val));
1352 else
1353 {
1354 /* Wrap VAL in an UNSPEC so that rx_is_legitimate_constant
1355 will not reject it. */
1356 val = gen_rtx_CONST (SImode, gen_rtx_UNSPEC (SImode, gen_rtvec (1, val), UNSPEC_CONST));
1357 insn = emit_insn (gen_addsi3 (dest, src, val));
1358
1359 if (is_frame_related)
1360 /* We have to provide our own frame related note here
1361 as the dwarf2out code cannot be expected to grok
1362 our unspec. */
1363 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
1364 gen_rtx_SET (SImode, dest,
1365 gen_rtx_PLUS (SImode, src, val)));
1366 return;
1367 }
1368
1369 if (is_frame_related)
1370 RTX_FRAME_RELATED_P (insn) = 1;
1371 return;
1372 }
1373
1374 void
1375 rx_expand_prologue (void)
1376 {
1377 unsigned int stack_size;
1378 unsigned int frame_size;
1379 unsigned int mask;
1380 unsigned int low;
1381 unsigned int high;
1382 unsigned int reg;
1383 rtx insn;
1384
1385 /* Naked functions use their own, programmer provided prologues. */
1386 if (is_naked_func (NULL_TREE))
1387 return;
1388
1389 rx_get_stack_layout (& low, & high, & mask, & frame_size, & stack_size);
1390
1391 /* If we use any of the callee-saved registers, save them now. */
1392 if (mask)
1393 {
1394 /* Push registers in reverse order. */
1395 for (reg = CC_REGNUM; reg --;)
1396 if (mask & (1 << reg))
1397 {
1398 insn = emit_insn (gen_stack_push (gen_rtx_REG (SImode, reg)));
1399 mark_frame_related (insn);
1400 }
1401 }
1402 else if (low)
1403 {
1404 if (high == low)
1405 insn = emit_insn (gen_stack_push (gen_rtx_REG (SImode, low)));
1406 else
1407 insn = emit_insn (gen_stack_pushm (GEN_INT (((high - low) + 1)
1408 * UNITS_PER_WORD),
1409 gen_rx_store_vector (low, high)));
1410 mark_frame_related (insn);
1411 }
1412
1413 if (MUST_SAVE_ACC_REGISTER)
1414 {
1415 unsigned int acc_high, acc_low;
1416
1417 /* Interrupt handlers have to preserve the accumulator
1418 register if so requested by the user. Use the first
1419 two pushed registers as intermediaries. */
1420 if (mask)
1421 {
1422 acc_low = acc_high = 0;
1423
1424 for (reg = 1; reg < CC_REGNUM; reg ++)
1425 if (mask & (1 << reg))
1426 {
1427 if (acc_low == 0)
1428 acc_low = reg;
1429 else
1430 {
1431 acc_high = reg;
1432 break;
1433 }
1434 }
1435
1436 /* We have assumed that there are at least two registers pushed... */
1437 gcc_assert (acc_high != 0);
1438
1439 /* Note - the bottom 16 bits of the accumulator are inaccessible.
1440 We just assume that they are zero. */
1441 emit_insn (gen_mvfacmi (gen_rtx_REG (SImode, acc_low)));
1442 emit_insn (gen_mvfachi (gen_rtx_REG (SImode, acc_high)));
1443 emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_low)));
1444 emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_high)));
1445 }
1446 else
1447 {
1448 acc_low = low;
1449 acc_high = low + 1;
1450
1451 /* We have assumed that there are at least two registers pushed... */
1452 gcc_assert (acc_high <= high);
1453
1454 emit_insn (gen_mvfacmi (gen_rtx_REG (SImode, acc_low)));
1455 emit_insn (gen_mvfachi (gen_rtx_REG (SImode, acc_high)));
1456 emit_insn (gen_stack_pushm (GEN_INT (2 * UNITS_PER_WORD),
1457 gen_rx_store_vector (acc_low, acc_high)));
1458 }
1459 }
1460
1461 /* If needed, set up the frame pointer. */
1462 if (frame_pointer_needed)
1463 gen_safe_add (frame_pointer_rtx, stack_pointer_rtx,
1464 GEN_INT (- (HOST_WIDE_INT) frame_size), true);
1465
1466 /* Allocate space for the outgoing args.
1467 If the stack frame has not already been set up then handle this as well. */
1468 if (stack_size)
1469 {
1470 if (frame_size)
1471 {
1472 if (frame_pointer_needed)
1473 gen_safe_add (stack_pointer_rtx, frame_pointer_rtx,
1474 GEN_INT (- (HOST_WIDE_INT) stack_size), true);
1475 else
1476 gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
1477 GEN_INT (- (HOST_WIDE_INT) (frame_size + stack_size)),
1478 true);
1479 }
1480 else
1481 gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
1482 GEN_INT (- (HOST_WIDE_INT) stack_size), true);
1483 }
1484 else if (frame_size)
1485 {
1486 if (! frame_pointer_needed)
1487 gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
1488 GEN_INT (- (HOST_WIDE_INT) frame_size), true);
1489 else
1490 gen_safe_add (stack_pointer_rtx, frame_pointer_rtx, NULL_RTX,
1491 true);
1492 }
1493 }
1494
1495 static void
1496 rx_output_function_prologue (FILE * file,
1497 HOST_WIDE_INT frame_size ATTRIBUTE_UNUSED)
1498 {
1499 if (is_fast_interrupt_func (NULL_TREE))
1500 asm_fprintf (file, "\t; Note: Fast Interrupt Handler\n");
1501
1502 if (is_interrupt_func (NULL_TREE))
1503 asm_fprintf (file, "\t; Note: Interrupt Handler\n");
1504
1505 if (is_naked_func (NULL_TREE))
1506 asm_fprintf (file, "\t; Note: Naked Function\n");
1507
1508 if (cfun->static_chain_decl != NULL)
1509 asm_fprintf (file, "\t; Note: Nested function declared "
1510 "inside another function.\n");
1511
1512 if (crtl->calls_eh_return)
1513 asm_fprintf (file, "\t; Note: Calls __builtin_eh_return.\n");
1514 }
1515
1516 /* Generate a POPM or RTSD instruction that matches the given operands. */
1517
1518 void
1519 rx_emit_stack_popm (rtx * operands, bool is_popm)
1520 {
1521 HOST_WIDE_INT stack_adjust;
1522 HOST_WIDE_INT last_reg;
1523 rtx first_push;
1524
1525 gcc_assert (CONST_INT_P (operands[0]));
1526 stack_adjust = INTVAL (operands[0]);
1527
1528 gcc_assert (GET_CODE (operands[1]) == PARALLEL);
1529 last_reg = XVECLEN (operands[1], 0) - (is_popm ? 2 : 3);
1530
1531 first_push = XVECEXP (operands[1], 0, 1);
1532 gcc_assert (SET_P (first_push));
1533 first_push = SET_DEST (first_push);
1534 gcc_assert (REG_P (first_push));
1535
1536 if (is_popm)
1537 asm_fprintf (asm_out_file, "\tpopm\t%s-%s\n",
1538 reg_names [REGNO (first_push)],
1539 reg_names [REGNO (first_push) + last_reg]);
1540 else
1541 asm_fprintf (asm_out_file, "\trtsd\t#%d, %s-%s\n",
1542 (int) stack_adjust,
1543 reg_names [REGNO (first_push)],
1544 reg_names [REGNO (first_push) + last_reg]);
1545 }
1546
1547 /* Generate a PARALLEL which will satisfy the rx_rtsd_vector predicate. */
1548
1549 static rtx
1550 gen_rx_rtsd_vector (unsigned int adjust, unsigned int low, unsigned int high)
1551 {
1552 unsigned int i;
1553 unsigned int bias = 3;
1554 unsigned int count = (high - low) + bias;
1555 rtx vector;
1556
1557 vector = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
1558
1559 XVECEXP (vector, 0, 0) =
1560 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
1561 plus_constant (stack_pointer_rtx, adjust));
1562
1563 for (i = 0; i < count - 2; i++)
1564 XVECEXP (vector, 0, i + 1) =
1565 gen_rtx_SET (VOIDmode,
1566 gen_rtx_REG (SImode, low + i),
1567 gen_rtx_MEM (SImode,
1568 i == 0 ? stack_pointer_rtx
1569 : plus_constant (stack_pointer_rtx,
1570 i * UNITS_PER_WORD)));
1571
1572 XVECEXP (vector, 0, count - 1) = ret_rtx;
1573
1574 return vector;
1575 }
1576
1577 /* Generate a PARALLEL which will satisfy the rx_load_multiple_vector predicate. */
1578
1579 static rtx
1580 gen_rx_popm_vector (unsigned int low, unsigned int high)
1581 {
1582 unsigned int i;
1583 unsigned int count = (high - low) + 2;
1584 rtx vector;
1585
1586 vector = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
1587
1588 XVECEXP (vector, 0, 0) =
1589 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
1590 plus_constant (stack_pointer_rtx,
1591 (count - 1) * UNITS_PER_WORD));
1592
1593 for (i = 0; i < count - 1; i++)
1594 XVECEXP (vector, 0, i + 1) =
1595 gen_rtx_SET (VOIDmode,
1596 gen_rtx_REG (SImode, low + i),
1597 gen_rtx_MEM (SImode,
1598 i == 0 ? stack_pointer_rtx
1599 : plus_constant (stack_pointer_rtx,
1600 i * UNITS_PER_WORD)));
1601
1602 return vector;
1603 }
1604
1605 void
1606 rx_expand_epilogue (bool is_sibcall)
1607 {
1608 unsigned int low;
1609 unsigned int high;
1610 unsigned int frame_size;
1611 unsigned int stack_size;
1612 unsigned int register_mask;
1613 unsigned int regs_size;
1614 unsigned int reg;
1615 unsigned HOST_WIDE_INT total_size;
1616
1617 /* FIXME: We do not support indirect sibcalls at the moment becaause we
1618 cannot guarantee that the register holding the function address is a
1619 call-used register. If it is a call-saved register then the stack
1620 pop instructions generated in the epilogue will corrupt the address
1621 before it is used.
1622
1623 Creating a new call-used-only register class works but then the
1624 reload pass gets stuck because it cannot always find a call-used
1625 register for spilling sibcalls.
1626
1627 The other possible solution is for this pass to scan forward for the
1628 sibcall instruction (if it has been generated) and work out if it
1629 is an indirect sibcall using a call-saved register. If it is then
1630 the address can copied into a call-used register in this epilogue
1631 code and the sibcall instruction modified to use that register. */
1632
1633 if (is_naked_func (NULL_TREE))
1634 {
1635 gcc_assert (! is_sibcall);
1636
1637 /* Naked functions use their own, programmer provided epilogues.
1638 But, in order to keep gcc happy we have to generate some kind of
1639 epilogue RTL. */
1640 emit_jump_insn (gen_naked_return ());
1641 return;
1642 }
1643
1644 rx_get_stack_layout (& low, & high, & register_mask,
1645 & frame_size, & stack_size);
1646
1647 total_size = frame_size + stack_size;
1648 regs_size = ((high - low) + 1) * UNITS_PER_WORD;
1649
1650 /* See if we are unable to use the special stack frame deconstruct and
1651 return instructions. In most cases we can use them, but the exceptions
1652 are:
1653
1654 - Sibling calling functions deconstruct the frame but do not return to
1655 their caller. Instead they branch to their sibling and allow their
1656 return instruction to return to this function's parent.
1657
1658 - Fast and normal interrupt handling functions have to use special
1659 return instructions.
1660
1661 - Functions where we have pushed a fragmented set of registers into the
1662 call-save area must have the same set of registers popped. */
1663 if (is_sibcall
1664 || is_fast_interrupt_func (NULL_TREE)
1665 || is_interrupt_func (NULL_TREE)
1666 || register_mask)
1667 {
1668 /* Cannot use the special instructions - deconstruct by hand. */
1669 if (total_size)
1670 gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
1671 GEN_INT (total_size), false);
1672
1673 if (MUST_SAVE_ACC_REGISTER)
1674 {
1675 unsigned int acc_low, acc_high;
1676
1677 /* Reverse the saving of the accumulator register onto the stack.
1678 Note we must adjust the saved "low" accumulator value as it
1679 is really the middle 32-bits of the accumulator. */
1680 if (register_mask)
1681 {
1682 acc_low = acc_high = 0;
1683
1684 for (reg = 1; reg < CC_REGNUM; reg ++)
1685 if (register_mask & (1 << reg))
1686 {
1687 if (acc_low == 0)
1688 acc_low = reg;
1689 else
1690 {
1691 acc_high = reg;
1692 break;
1693 }
1694 }
1695 emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_high)));
1696 emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_low)));
1697 }
1698 else
1699 {
1700 acc_low = low;
1701 acc_high = low + 1;
1702 emit_insn (gen_stack_popm (GEN_INT (2 * UNITS_PER_WORD),
1703 gen_rx_popm_vector (acc_low, acc_high)));
1704 }
1705
1706 emit_insn (gen_ashlsi3 (gen_rtx_REG (SImode, acc_low),
1707 gen_rtx_REG (SImode, acc_low),
1708 GEN_INT (16)));
1709 emit_insn (gen_mvtaclo (gen_rtx_REG (SImode, acc_low)));
1710 emit_insn (gen_mvtachi (gen_rtx_REG (SImode, acc_high)));
1711 }
1712
1713 if (register_mask)
1714 {
1715 for (reg = 0; reg < CC_REGNUM; reg ++)
1716 if (register_mask & (1 << reg))
1717 emit_insn (gen_stack_pop (gen_rtx_REG (SImode, reg)));
1718 }
1719 else if (low)
1720 {
1721 if (high == low)
1722 emit_insn (gen_stack_pop (gen_rtx_REG (SImode, low)));
1723 else
1724 emit_insn (gen_stack_popm (GEN_INT (regs_size),
1725 gen_rx_popm_vector (low, high)));
1726 }
1727
1728 if (is_fast_interrupt_func (NULL_TREE))
1729 {
1730 gcc_assert (! is_sibcall);
1731 emit_jump_insn (gen_fast_interrupt_return ());
1732 }
1733 else if (is_interrupt_func (NULL_TREE))
1734 {
1735 gcc_assert (! is_sibcall);
1736 emit_jump_insn (gen_exception_return ());
1737 }
1738 else if (! is_sibcall)
1739 emit_jump_insn (gen_simple_return ());
1740
1741 return;
1742 }
1743
1744 /* If we allocated space on the stack, free it now. */
1745 if (total_size)
1746 {
1747 unsigned HOST_WIDE_INT rtsd_size;
1748
1749 /* See if we can use the RTSD instruction. */
1750 rtsd_size = total_size + regs_size;
1751 if (rtsd_size < 1024 && (rtsd_size % 4) == 0)
1752 {
1753 if (low)
1754 emit_jump_insn (gen_pop_and_return
1755 (GEN_INT (rtsd_size),
1756 gen_rx_rtsd_vector (rtsd_size, low, high)));
1757 else
1758 emit_jump_insn (gen_deallocate_and_return (GEN_INT (total_size)));
1759
1760 return;
1761 }
1762
1763 gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
1764 GEN_INT (total_size), false);
1765 }
1766
1767 if (low)
1768 emit_jump_insn (gen_pop_and_return (GEN_INT (regs_size),
1769 gen_rx_rtsd_vector (regs_size,
1770 low, high)));
1771 else
1772 emit_jump_insn (gen_simple_return ());
1773 }
1774
1775
1776 /* Compute the offset (in words) between FROM (arg pointer
1777 or frame pointer) and TO (frame pointer or stack pointer).
1778 See ASCII art comment at the start of rx_expand_prologue
1779 for more information. */
1780
1781 int
1782 rx_initial_elimination_offset (int from, int to)
1783 {
1784 unsigned int low;
1785 unsigned int high;
1786 unsigned int frame_size;
1787 unsigned int stack_size;
1788 unsigned int mask;
1789
1790 rx_get_stack_layout (& low, & high, & mask, & frame_size, & stack_size);
1791
1792 if (from == ARG_POINTER_REGNUM)
1793 {
1794 /* Extend the computed size of the stack frame to
1795 include the registers pushed in the prologue. */
1796 if (low)
1797 frame_size += ((high - low) + 1) * UNITS_PER_WORD;
1798 else
1799 frame_size += bit_count (mask) * UNITS_PER_WORD;
1800
1801 /* Remember to include the return address. */
1802 frame_size += 1 * UNITS_PER_WORD;
1803
1804 if (to == FRAME_POINTER_REGNUM)
1805 return frame_size;
1806
1807 gcc_assert (to == STACK_POINTER_REGNUM);
1808 return frame_size + stack_size;
1809 }
1810
1811 gcc_assert (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM);
1812 return stack_size;
1813 }
1814
1815 /* Decide if a variable should go into one of the small data sections. */
1816
1817 static bool
1818 rx_in_small_data (const_tree decl)
1819 {
1820 int size;
1821 const_tree section;
1822
1823 if (rx_small_data_limit == 0)
1824 return false;
1825
1826 if (TREE_CODE (decl) != VAR_DECL)
1827 return false;
1828
1829 /* We do not put read-only variables into a small data area because
1830 they would be placed with the other read-only sections, far away
1831 from the read-write data sections, and we only have one small
1832 data area pointer.
1833 Similarly commons are placed in the .bss section which might be
1834 far away (and out of alignment with respect to) the .data section. */
1835 if (TREE_READONLY (decl) || DECL_COMMON (decl))
1836 return false;
1837
1838 section = DECL_SECTION_NAME (decl);
1839 if (section)
1840 {
1841 const char * const name = TREE_STRING_POINTER (section);
1842
1843 return (strcmp (name, "D_2") == 0) || (strcmp (name, "B_2") == 0);
1844 }
1845
1846 size = int_size_in_bytes (TREE_TYPE (decl));
1847
1848 return (size > 0) && (size <= rx_small_data_limit);
1849 }
1850
1851 /* Return a section for X.
1852 The only special thing we do here is to honor small data. */
1853
1854 static section *
1855 rx_select_rtx_section (enum machine_mode mode,
1856 rtx x,
1857 unsigned HOST_WIDE_INT align)
1858 {
1859 if (rx_small_data_limit > 0
1860 && GET_MODE_SIZE (mode) <= rx_small_data_limit
1861 && align <= (unsigned HOST_WIDE_INT) rx_small_data_limit * BITS_PER_UNIT)
1862 return sdata_section;
1863
1864 return default_elf_select_rtx_section (mode, x, align);
1865 }
1866
1867 static section *
1868 rx_select_section (tree decl,
1869 int reloc,
1870 unsigned HOST_WIDE_INT align)
1871 {
1872 if (rx_small_data_limit > 0)
1873 {
1874 switch (categorize_decl_for_section (decl, reloc))
1875 {
1876 case SECCAT_SDATA: return sdata_section;
1877 case SECCAT_SBSS: return sbss_section;
1878 case SECCAT_SRODATA:
1879 /* Fall through. We do not put small, read only
1880 data into the C_2 section because we are not
1881 using the C_2 section. We do not use the C_2
1882 section because it is located with the other
1883 read-only data sections, far away from the read-write
1884 data sections and we only have one small data
1885 pointer (r13). */
1886 default:
1887 break;
1888 }
1889 }
1890
1891 /* If we are supporting the Renesas assembler
1892 we cannot use mergeable sections. */
1893 if (TARGET_AS100_SYNTAX)
1894 switch (categorize_decl_for_section (decl, reloc))
1895 {
1896 case SECCAT_RODATA_MERGE_CONST:
1897 case SECCAT_RODATA_MERGE_STR_INIT:
1898 case SECCAT_RODATA_MERGE_STR:
1899 return readonly_data_section;
1900
1901 default:
1902 break;
1903 }
1904
1905 return default_elf_select_section (decl, reloc, align);
1906 }
1907 \f
1908 enum rx_builtin
1909 {
1910 RX_BUILTIN_BRK,
1911 RX_BUILTIN_CLRPSW,
1912 RX_BUILTIN_INT,
1913 RX_BUILTIN_MACHI,
1914 RX_BUILTIN_MACLO,
1915 RX_BUILTIN_MULHI,
1916 RX_BUILTIN_MULLO,
1917 RX_BUILTIN_MVFACHI,
1918 RX_BUILTIN_MVFACMI,
1919 RX_BUILTIN_MVFC,
1920 RX_BUILTIN_MVTACHI,
1921 RX_BUILTIN_MVTACLO,
1922 RX_BUILTIN_MVTC,
1923 RX_BUILTIN_MVTIPL,
1924 RX_BUILTIN_RACW,
1925 RX_BUILTIN_REVW,
1926 RX_BUILTIN_RMPA,
1927 RX_BUILTIN_ROUND,
1928 RX_BUILTIN_SETPSW,
1929 RX_BUILTIN_WAIT,
1930 RX_BUILTIN_max
1931 };
1932
1933 static GTY(()) tree rx_builtins[(int) RX_BUILTIN_max];
1934
1935 static void
1936 rx_init_builtins (void)
1937 {
1938 #define ADD_RX_BUILTIN1(UC_NAME, LC_NAME, RET_TYPE, ARG_TYPE) \
1939 rx_builtins[RX_BUILTIN_##UC_NAME] = \
1940 add_builtin_function ("__builtin_rx_" LC_NAME, \
1941 build_function_type_list (RET_TYPE##_type_node, \
1942 ARG_TYPE##_type_node, \
1943 NULL_TREE), \
1944 RX_BUILTIN_##UC_NAME, \
1945 BUILT_IN_MD, NULL, NULL_TREE)
1946
1947 #define ADD_RX_BUILTIN2(UC_NAME, LC_NAME, RET_TYPE, ARG_TYPE1, ARG_TYPE2) \
1948 rx_builtins[RX_BUILTIN_##UC_NAME] = \
1949 add_builtin_function ("__builtin_rx_" LC_NAME, \
1950 build_function_type_list (RET_TYPE##_type_node, \
1951 ARG_TYPE1##_type_node,\
1952 ARG_TYPE2##_type_node,\
1953 NULL_TREE), \
1954 RX_BUILTIN_##UC_NAME, \
1955 BUILT_IN_MD, NULL, NULL_TREE)
1956
1957 #define ADD_RX_BUILTIN3(UC_NAME,LC_NAME,RET_TYPE,ARG_TYPE1,ARG_TYPE2,ARG_TYPE3) \
1958 rx_builtins[RX_BUILTIN_##UC_NAME] = \
1959 add_builtin_function ("__builtin_rx_" LC_NAME, \
1960 build_function_type_list (RET_TYPE##_type_node, \
1961 ARG_TYPE1##_type_node,\
1962 ARG_TYPE2##_type_node,\
1963 ARG_TYPE3##_type_node,\
1964 NULL_TREE), \
1965 RX_BUILTIN_##UC_NAME, \
1966 BUILT_IN_MD, NULL, NULL_TREE)
1967
1968 ADD_RX_BUILTIN1 (BRK, "brk", void, void);
1969 ADD_RX_BUILTIN1 (CLRPSW, "clrpsw", void, integer);
1970 ADD_RX_BUILTIN1 (SETPSW, "setpsw", void, integer);
1971 ADD_RX_BUILTIN1 (INT, "int", void, integer);
1972 ADD_RX_BUILTIN2 (MACHI, "machi", void, intSI, intSI);
1973 ADD_RX_BUILTIN2 (MACLO, "maclo", void, intSI, intSI);
1974 ADD_RX_BUILTIN2 (MULHI, "mulhi", void, intSI, intSI);
1975 ADD_RX_BUILTIN2 (MULLO, "mullo", void, intSI, intSI);
1976 ADD_RX_BUILTIN1 (MVFACHI, "mvfachi", intSI, void);
1977 ADD_RX_BUILTIN1 (MVFACMI, "mvfacmi", intSI, void);
1978 ADD_RX_BUILTIN1 (MVTACHI, "mvtachi", void, intSI);
1979 ADD_RX_BUILTIN1 (MVTACLO, "mvtaclo", void, intSI);
1980 ADD_RX_BUILTIN1 (RMPA, "rmpa", void, void);
1981 ADD_RX_BUILTIN1 (MVFC, "mvfc", intSI, integer);
1982 ADD_RX_BUILTIN2 (MVTC, "mvtc", void, integer, integer);
1983 ADD_RX_BUILTIN1 (MVTIPL, "mvtipl", void, integer);
1984 ADD_RX_BUILTIN1 (RACW, "racw", void, integer);
1985 ADD_RX_BUILTIN1 (ROUND, "round", intSI, float);
1986 ADD_RX_BUILTIN1 (REVW, "revw", intSI, intSI);
1987 ADD_RX_BUILTIN1 (WAIT, "wait", void, void);
1988 }
1989
1990 /* Return the RX builtin for CODE. */
1991
1992 static tree
1993 rx_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
1994 {
1995 if (code >= RX_BUILTIN_max)
1996 return error_mark_node;
1997
1998 return rx_builtins[code];
1999 }
2000
2001 static rtx
2002 rx_expand_void_builtin_1_arg (rtx arg, rtx (* gen_func)(rtx), bool reg)
2003 {
2004 if (reg && ! REG_P (arg))
2005 arg = force_reg (SImode, arg);
2006
2007 emit_insn (gen_func (arg));
2008
2009 return NULL_RTX;
2010 }
2011
2012 static rtx
2013 rx_expand_builtin_mvtc (tree exp)
2014 {
2015 rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
2016 rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1));
2017
2018 if (! CONST_INT_P (arg1))
2019 return NULL_RTX;
2020
2021 if (! REG_P (arg2))
2022 arg2 = force_reg (SImode, arg2);
2023
2024 emit_insn (gen_mvtc (arg1, arg2));
2025
2026 return NULL_RTX;
2027 }
2028
2029 static rtx
2030 rx_expand_builtin_mvfc (tree t_arg, rtx target)
2031 {
2032 rtx arg = expand_normal (t_arg);
2033
2034 if (! CONST_INT_P (arg))
2035 return NULL_RTX;
2036
2037 if (target == NULL_RTX)
2038 return NULL_RTX;
2039
2040 if (! REG_P (target))
2041 target = force_reg (SImode, target);
2042
2043 emit_insn (gen_mvfc (target, arg));
2044
2045 return target;
2046 }
2047
2048 static rtx
2049 rx_expand_builtin_mvtipl (rtx arg)
2050 {
2051 /* The RX610 does not support the MVTIPL instruction. */
2052 if (rx_cpu_type == RX610)
2053 return NULL_RTX;
2054
2055 if (! CONST_INT_P (arg) || ! IN_RANGE (INTVAL (arg), 0, (1 << 4) - 1))
2056 return NULL_RTX;
2057
2058 emit_insn (gen_mvtipl (arg));
2059
2060 return NULL_RTX;
2061 }
2062
2063 static rtx
2064 rx_expand_builtin_mac (tree exp, rtx (* gen_func)(rtx, rtx))
2065 {
2066 rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
2067 rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1));
2068
2069 if (! REG_P (arg1))
2070 arg1 = force_reg (SImode, arg1);
2071
2072 if (! REG_P (arg2))
2073 arg2 = force_reg (SImode, arg2);
2074
2075 emit_insn (gen_func (arg1, arg2));
2076
2077 return NULL_RTX;
2078 }
2079
2080 static rtx
2081 rx_expand_int_builtin_1_arg (rtx arg,
2082 rtx target,
2083 rtx (* gen_func)(rtx, rtx),
2084 bool mem_ok)
2085 {
2086 if (! REG_P (arg))
2087 if (!mem_ok || ! MEM_P (arg))
2088 arg = force_reg (SImode, arg);
2089
2090 if (target == NULL_RTX || ! REG_P (target))
2091 target = gen_reg_rtx (SImode);
2092
2093 emit_insn (gen_func (target, arg));
2094
2095 return target;
2096 }
2097
2098 static rtx
2099 rx_expand_int_builtin_0_arg (rtx target, rtx (* gen_func)(rtx))
2100 {
2101 if (target == NULL_RTX || ! REG_P (target))
2102 target = gen_reg_rtx (SImode);
2103
2104 emit_insn (gen_func (target));
2105
2106 return target;
2107 }
2108
2109 static rtx
2110 rx_expand_builtin_round (rtx arg, rtx target)
2111 {
2112 if ((! REG_P (arg) && ! MEM_P (arg))
2113 || GET_MODE (arg) != SFmode)
2114 arg = force_reg (SFmode, arg);
2115
2116 if (target == NULL_RTX || ! REG_P (target))
2117 target = gen_reg_rtx (SImode);
2118
2119 emit_insn (gen_lrintsf2 (target, arg));
2120
2121 return target;
2122 }
2123
2124 static int
2125 valid_psw_flag (rtx op, const char *which)
2126 {
2127 static int mvtc_inform_done = 0;
2128
2129 if (GET_CODE (op) == CONST_INT)
2130 switch (INTVAL (op))
2131 {
2132 case 0: case 'c': case 'C':
2133 case 1: case 'z': case 'Z':
2134 case 2: case 's': case 'S':
2135 case 3: case 'o': case 'O':
2136 case 8: case 'i': case 'I':
2137 case 9: case 'u': case 'U':
2138 return 1;
2139 }
2140
2141 error ("__builtin_rx_%s takes 'C', 'Z', 'S', 'O', 'I', or 'U'", which);
2142 if (!mvtc_inform_done)
2143 error ("use __builtin_rx_mvtc (0, ... ) to write arbitrary values to PSW");
2144 mvtc_inform_done = 1;
2145
2146 return 0;
2147 }
2148
2149 static rtx
2150 rx_expand_builtin (tree exp,
2151 rtx target,
2152 rtx subtarget ATTRIBUTE_UNUSED,
2153 enum machine_mode mode ATTRIBUTE_UNUSED,
2154 int ignore ATTRIBUTE_UNUSED)
2155 {
2156 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
2157 tree arg = call_expr_nargs (exp) >= 1 ? CALL_EXPR_ARG (exp, 0) : NULL_TREE;
2158 rtx op = arg ? expand_normal (arg) : NULL_RTX;
2159 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2160
2161 switch (fcode)
2162 {
2163 case RX_BUILTIN_BRK: emit_insn (gen_brk ()); return NULL_RTX;
2164 case RX_BUILTIN_CLRPSW:
2165 if (!valid_psw_flag (op, "clrpsw"))
2166 return NULL_RTX;
2167 return rx_expand_void_builtin_1_arg (op, gen_clrpsw, false);
2168 case RX_BUILTIN_SETPSW:
2169 if (!valid_psw_flag (op, "setpsw"))
2170 return NULL_RTX;
2171 return rx_expand_void_builtin_1_arg (op, gen_setpsw, false);
2172 case RX_BUILTIN_INT: return rx_expand_void_builtin_1_arg
2173 (op, gen_int, false);
2174 case RX_BUILTIN_MACHI: return rx_expand_builtin_mac (exp, gen_machi);
2175 case RX_BUILTIN_MACLO: return rx_expand_builtin_mac (exp, gen_maclo);
2176 case RX_BUILTIN_MULHI: return rx_expand_builtin_mac (exp, gen_mulhi);
2177 case RX_BUILTIN_MULLO: return rx_expand_builtin_mac (exp, gen_mullo);
2178 case RX_BUILTIN_MVFACHI: return rx_expand_int_builtin_0_arg
2179 (target, gen_mvfachi);
2180 case RX_BUILTIN_MVFACMI: return rx_expand_int_builtin_0_arg
2181 (target, gen_mvfacmi);
2182 case RX_BUILTIN_MVTACHI: return rx_expand_void_builtin_1_arg
2183 (op, gen_mvtachi, true);
2184 case RX_BUILTIN_MVTACLO: return rx_expand_void_builtin_1_arg
2185 (op, gen_mvtaclo, true);
2186 case RX_BUILTIN_RMPA: emit_insn (gen_rmpa ()); return NULL_RTX;
2187 case RX_BUILTIN_MVFC: return rx_expand_builtin_mvfc (arg, target);
2188 case RX_BUILTIN_MVTC: return rx_expand_builtin_mvtc (exp);
2189 case RX_BUILTIN_MVTIPL: return rx_expand_builtin_mvtipl (op);
2190 case RX_BUILTIN_RACW: return rx_expand_void_builtin_1_arg
2191 (op, gen_racw, false);
2192 case RX_BUILTIN_ROUND: return rx_expand_builtin_round (op, target);
2193 case RX_BUILTIN_REVW: return rx_expand_int_builtin_1_arg
2194 (op, target, gen_revw, false);
2195 case RX_BUILTIN_WAIT: emit_insn (gen_wait ()); return NULL_RTX;
2196
2197 default:
2198 internal_error ("bad builtin code");
2199 break;
2200 }
2201
2202 return NULL_RTX;
2203 }
2204 \f
2205 /* Place an element into a constructor or destructor section.
2206 Like default_ctor_section_asm_out_constructor in varasm.c
2207 except that it uses .init_array (or .fini_array) and it
2208 handles constructor priorities. */
2209
2210 static void
2211 rx_elf_asm_cdtor (rtx symbol, int priority, bool is_ctor)
2212 {
2213 section * s;
2214
2215 if (priority != DEFAULT_INIT_PRIORITY)
2216 {
2217 char buf[18];
2218
2219 sprintf (buf, "%s.%.5u",
2220 is_ctor ? ".init_array" : ".fini_array",
2221 priority);
2222 s = get_section (buf, SECTION_WRITE, NULL_TREE);
2223 }
2224 else if (is_ctor)
2225 s = ctors_section;
2226 else
2227 s = dtors_section;
2228
2229 switch_to_section (s);
2230 assemble_align (POINTER_SIZE);
2231 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
2232 }
2233
2234 static void
2235 rx_elf_asm_constructor (rtx symbol, int priority)
2236 {
2237 rx_elf_asm_cdtor (symbol, priority, /* is_ctor= */true);
2238 }
2239
2240 static void
2241 rx_elf_asm_destructor (rtx symbol, int priority)
2242 {
2243 rx_elf_asm_cdtor (symbol, priority, /* is_ctor= */false);
2244 }
2245 \f
2246 /* Check "fast_interrupt", "interrupt" and "naked" attributes. */
2247
2248 static tree
2249 rx_handle_func_attribute (tree * node,
2250 tree name,
2251 tree args,
2252 int flags ATTRIBUTE_UNUSED,
2253 bool * no_add_attrs)
2254 {
2255 gcc_assert (DECL_P (* node));
2256 gcc_assert (args == NULL_TREE);
2257
2258 if (TREE_CODE (* node) != FUNCTION_DECL)
2259 {
2260 warning (OPT_Wattributes, "%qE attribute only applies to functions",
2261 name);
2262 * no_add_attrs = true;
2263 }
2264
2265 /* FIXME: We ought to check for conflicting attributes. */
2266
2267 /* FIXME: We ought to check that the interrupt and exception
2268 handler attributes have been applied to void functions. */
2269 return NULL_TREE;
2270 }
2271
2272 /* Table of RX specific attributes. */
2273 const struct attribute_spec rx_attribute_table[] =
2274 {
2275 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
2276 affects_type_identity. */
2277 { "fast_interrupt", 0, 0, true, false, false, rx_handle_func_attribute,
2278 false },
2279 { "interrupt", 0, 0, true, false, false, rx_handle_func_attribute,
2280 false },
2281 { "naked", 0, 0, true, false, false, rx_handle_func_attribute,
2282 false },
2283 { NULL, 0, 0, false, false, false, NULL, false }
2284 };
2285
2286 /* Extra processing for target specific command line options. */
2287
2288 static bool
2289 rx_handle_option (struct gcc_options *opts,
2290 struct gcc_options *opts_set ATTRIBUTE_UNUSED,
2291 const struct cl_decoded_option *decoded,
2292 location_t loc)
2293 {
2294 size_t code = decoded->opt_index;
2295 int value = decoded->value;
2296
2297 switch (code)
2298 {
2299 case OPT_mint_register_:
2300 /* Make sure that the -mint-register option is in range. Other
2301 handling in rx_option_override. */
2302 return value >= 0 && value <= 4;
2303 break;
2304
2305 case OPT_mmax_constant_size_:
2306 /* Make sure that the -mmax-constant_size option is in range. */
2307 return value >= 0 && value <= 4;
2308
2309 case OPT_mcpu_:
2310 if ((enum rx_cpu_types) value == RX200)
2311 opts->x_target_flags |= MASK_NO_USE_FPU;
2312 break;
2313
2314 case OPT_fpu:
2315 if (opts->x_rx_cpu_type == RX200)
2316 error_at (loc, "the RX200 cpu does not have FPU hardware");
2317 break;
2318
2319 default:
2320 break;
2321 }
2322
2323 return true;
2324 }
2325
2326 /* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE. */
2327
2328 static void
2329 rx_override_options_after_change (void)
2330 {
2331 static bool first_time = TRUE;
2332
2333 if (first_time)
2334 {
2335 /* If this is the first time through and the user has not disabled
2336 the use of RX FPU hardware then enable -ffinite-math-only,
2337 since the FPU instructions do not support NaNs and infinities. */
2338 if (TARGET_USE_FPU)
2339 flag_finite_math_only = 1;
2340
2341 first_time = FALSE;
2342 }
2343 else
2344 {
2345 /* Alert the user if they are changing the optimization options
2346 to use IEEE compliant floating point arithmetic with RX FPU insns. */
2347 if (TARGET_USE_FPU
2348 && !flag_finite_math_only)
2349 warning (0, "RX FPU instructions do not support NaNs and infinities");
2350 }
2351 }
2352
2353 static void
2354 rx_option_override (void)
2355 {
2356 unsigned int i;
2357 cl_deferred_option *opt;
2358 VEC(cl_deferred_option,heap) *vec
2359 = (VEC(cl_deferred_option,heap) *) rx_deferred_options;
2360
2361 FOR_EACH_VEC_ELT (cl_deferred_option, vec, i, opt)
2362 {
2363 switch (opt->opt_index)
2364 {
2365 case OPT_mint_register_:
2366 switch (opt->value)
2367 {
2368 case 4:
2369 fixed_regs[10] = call_used_regs [10] = 1;
2370 /* Fall through. */
2371 case 3:
2372 fixed_regs[11] = call_used_regs [11] = 1;
2373 /* Fall through. */
2374 case 2:
2375 fixed_regs[12] = call_used_regs [12] = 1;
2376 /* Fall through. */
2377 case 1:
2378 fixed_regs[13] = call_used_regs [13] = 1;
2379 /* Fall through. */
2380 case 0:
2381 break;
2382 default:
2383 /* Error message already given because rx_handle_option
2384 returned false. */
2385 break;
2386 }
2387 break;
2388
2389 default:
2390 gcc_unreachable ();
2391 }
2392 }
2393
2394 /* This target defaults to strict volatile bitfields. */
2395 if (flag_strict_volatile_bitfields < 0)
2396 flag_strict_volatile_bitfields = 1;
2397
2398 rx_override_options_after_change ();
2399
2400 if (align_jumps == 0 && ! optimize_size)
2401 align_jumps = 3;
2402 if (align_loops == 0 && ! optimize_size)
2403 align_loops = 3;
2404 if (align_labels == 0 && ! optimize_size)
2405 align_labels = 3;
2406 }
2407
2408 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */
2409 static const struct default_options rx_option_optimization_table[] =
2410 {
2411 { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
2412 { OPT_LEVELS_NONE, 0, NULL, 0 }
2413 };
2414
2415 \f
2416 static bool
2417 rx_allocate_stack_slots_for_args (void)
2418 {
2419 /* Naked functions should not allocate stack slots for arguments. */
2420 return ! is_naked_func (NULL_TREE);
2421 }
2422
2423 static bool
2424 rx_func_attr_inlinable (const_tree decl)
2425 {
2426 return ! is_fast_interrupt_func (decl)
2427 && ! is_interrupt_func (decl)
2428 && ! is_naked_func (decl);
2429 }
2430
2431 /* Return nonzero if it is ok to make a tail-call to DECL,
2432 a function_decl or NULL if this is an indirect call, using EXP */
2433
2434 static bool
2435 rx_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
2436 {
2437 /* Do not allow indirect tailcalls. The
2438 sibcall patterns do not support them. */
2439 if (decl == NULL)
2440 return false;
2441
2442 /* Never tailcall from inside interrupt handlers or naked functions. */
2443 if (is_fast_interrupt_func (NULL_TREE)
2444 || is_interrupt_func (NULL_TREE)
2445 || is_naked_func (NULL_TREE))
2446 return false;
2447
2448 return true;
2449 }
2450
2451 static void
2452 rx_file_start (void)
2453 {
2454 if (! TARGET_AS100_SYNTAX)
2455 default_file_start ();
2456 }
2457
2458 static bool
2459 rx_is_ms_bitfield_layout (const_tree record_type ATTRIBUTE_UNUSED)
2460 {
2461 /* The packed attribute overrides the MS behaviour. */
2462 return ! TYPE_PACKED (record_type);
2463 }
2464 \f
2465 /* Returns true if X a legitimate constant for an immediate
2466 operand on the RX. X is already known to satisfy CONSTANT_P. */
2467
2468 bool
2469 rx_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
2470 {
2471 switch (GET_CODE (x))
2472 {
2473 case CONST:
2474 x = XEXP (x, 0);
2475
2476 if (GET_CODE (x) == PLUS)
2477 {
2478 if (! CONST_INT_P (XEXP (x, 1)))
2479 return false;
2480
2481 /* GCC would not pass us CONST_INT + CONST_INT so we
2482 know that we have {SYMBOL|LABEL} + CONST_INT. */
2483 x = XEXP (x, 0);
2484 gcc_assert (! CONST_INT_P (x));
2485 }
2486
2487 switch (GET_CODE (x))
2488 {
2489 case LABEL_REF:
2490 case SYMBOL_REF:
2491 return true;
2492
2493 case UNSPEC:
2494 return XINT (x, 1) == UNSPEC_CONST;
2495
2496 default:
2497 /* FIXME: Can this ever happen ? */
2498 gcc_unreachable ();
2499 }
2500 break;
2501
2502 case LABEL_REF:
2503 case SYMBOL_REF:
2504 return true;
2505 case CONST_DOUBLE:
2506 return (rx_max_constant_size == 0 || rx_max_constant_size == 4);
2507 case CONST_VECTOR:
2508 return false;
2509 default:
2510 gcc_assert (CONST_INT_P (x));
2511 break;
2512 }
2513
2514 return ok_for_max_constant (INTVAL (x));
2515 }
2516
2517 static int
2518 rx_address_cost (rtx addr, bool speed)
2519 {
2520 rtx a, b;
2521
2522 if (GET_CODE (addr) != PLUS)
2523 return COSTS_N_INSNS (1);
2524
2525 a = XEXP (addr, 0);
2526 b = XEXP (addr, 1);
2527
2528 if (REG_P (a) && REG_P (b))
2529 /* Try to discourage REG+REG addressing as it keeps two registers live. */
2530 return COSTS_N_INSNS (4);
2531
2532 if (speed)
2533 /* [REG+OFF] is just as fast as [REG]. */
2534 return COSTS_N_INSNS (1);
2535
2536 if (CONST_INT_P (b)
2537 && ((INTVAL (b) > 128) || INTVAL (b) < -127))
2538 /* Try to discourage REG + <large OFF> when optimizing for size. */
2539 return COSTS_N_INSNS (2);
2540
2541 return COSTS_N_INSNS (1);
2542 }
2543
2544 static bool
2545 rx_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
2546 {
2547 /* We can always eliminate to the frame pointer.
2548 We can eliminate to the stack pointer unless a frame
2549 pointer is needed. */
2550
2551 return to == FRAME_POINTER_REGNUM
2552 || ( to == STACK_POINTER_REGNUM && ! frame_pointer_needed);
2553 }
2554 \f
2555
2556 static void
2557 rx_trampoline_template (FILE * file)
2558 {
2559 /* Output assembler code for a block containing the constant
2560 part of a trampoline, leaving space for the variable parts.
2561
2562 On the RX, (where r8 is the static chain regnum) the trampoline
2563 looks like:
2564
2565 mov #<static chain value>, r8
2566 mov #<function's address>, r9
2567 jmp r9
2568
2569 In big-endian-data-mode however instructions are read into the CPU
2570 4 bytes at a time. These bytes are then swapped around before being
2571 passed to the decoder. So...we must partition our trampoline into
2572 4 byte packets and swap these packets around so that the instruction
2573 reader will reverse the process. But, in order to avoid splitting
2574 the 32-bit constants across these packet boundaries, (making inserting
2575 them into the constructed trampoline very difficult) we have to pad the
2576 instruction sequence with NOP insns. ie:
2577
2578 nop
2579 nop
2580 mov.l #<...>, r8
2581 nop
2582 nop
2583 mov.l #<...>, r9
2584 jmp r9
2585 nop
2586 nop */
2587
2588 if (! TARGET_BIG_ENDIAN_DATA)
2589 {
2590 asm_fprintf (file, "\tmov.L\t#0deadbeefH, r%d\n", STATIC_CHAIN_REGNUM);
2591 asm_fprintf (file, "\tmov.L\t#0deadbeefH, r%d\n", TRAMPOLINE_TEMP_REGNUM);
2592 asm_fprintf (file, "\tjmp\tr%d\n", TRAMPOLINE_TEMP_REGNUM);
2593 }
2594 else
2595 {
2596 char r8 = '0' + STATIC_CHAIN_REGNUM;
2597 char r9 = '0' + TRAMPOLINE_TEMP_REGNUM;
2598
2599 if (TARGET_AS100_SYNTAX)
2600 {
2601 asm_fprintf (file, "\t.BYTE 0%c2H, 0fbH, 003H, 003H\n", r8);
2602 asm_fprintf (file, "\t.BYTE 0deH, 0adH, 0beH, 0efH\n");
2603 asm_fprintf (file, "\t.BYTE 0%c2H, 0fbH, 003H, 003H\n", r9);
2604 asm_fprintf (file, "\t.BYTE 0deH, 0adH, 0beH, 0efH\n");
2605 asm_fprintf (file, "\t.BYTE 003H, 003H, 00%cH, 07fH\n", r9);
2606 }
2607 else
2608 {
2609 asm_fprintf (file, "\t.byte 0x%c2, 0xfb, 0x03, 0x03\n", r8);
2610 asm_fprintf (file, "\t.byte 0xde, 0xad, 0xbe, 0xef\n");
2611 asm_fprintf (file, "\t.byte 0x%c2, 0xfb, 0x03, 0x03\n", r9);
2612 asm_fprintf (file, "\t.byte 0xde, 0xad, 0xbe, 0xef\n");
2613 asm_fprintf (file, "\t.byte 0x03, 0x03, 0x0%c, 0x7f\n", r9);
2614 }
2615 }
2616 }
2617
2618 static void
2619 rx_trampoline_init (rtx tramp, tree fndecl, rtx chain)
2620 {
2621 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
2622
2623 emit_block_move (tramp, assemble_trampoline_template (),
2624 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
2625
2626 if (TARGET_BIG_ENDIAN_DATA)
2627 {
2628 emit_move_insn (adjust_address (tramp, SImode, 4), chain);
2629 emit_move_insn (adjust_address (tramp, SImode, 12), fnaddr);
2630 }
2631 else
2632 {
2633 emit_move_insn (adjust_address (tramp, SImode, 2), chain);
2634 emit_move_insn (adjust_address (tramp, SImode, 6 + 2), fnaddr);
2635 }
2636 }
2637 \f
2638 static int
2639 rx_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
2640 reg_class_t regclass ATTRIBUTE_UNUSED,
2641 bool in)
2642 {
2643 return (in ? 2 : 0) + REGISTER_MOVE_COST (mode, regclass, regclass);
2644 }
2645
2646 /* Convert a CC_MODE to the set of flags that it represents. */
2647
2648 static unsigned int
2649 flags_from_mode (enum machine_mode mode)
2650 {
2651 switch (mode)
2652 {
2653 case CC_ZSmode:
2654 return CC_FLAG_S | CC_FLAG_Z;
2655 case CC_ZSOmode:
2656 return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_O;
2657 case CC_ZSCmode:
2658 return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_C;
2659 case CCmode:
2660 return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_O | CC_FLAG_C;
2661 case CC_Fmode:
2662 return CC_FLAG_FP;
2663 default:
2664 gcc_unreachable ();
2665 }
2666 }
2667
2668 /* Convert a set of flags to a CC_MODE that can implement it. */
2669
2670 static enum machine_mode
2671 mode_from_flags (unsigned int f)
2672 {
2673 if (f & CC_FLAG_FP)
2674 return CC_Fmode;
2675 if (f & CC_FLAG_O)
2676 {
2677 if (f & CC_FLAG_C)
2678 return CCmode;
2679 else
2680 return CC_ZSOmode;
2681 }
2682 else if (f & CC_FLAG_C)
2683 return CC_ZSCmode;
2684 else
2685 return CC_ZSmode;
2686 }
2687
2688 /* Convert an RTX_CODE to the set of flags needed to implement it.
2689 This assumes an integer comparison. */
2690
2691 static unsigned int
2692 flags_from_code (enum rtx_code code)
2693 {
2694 switch (code)
2695 {
2696 case LT:
2697 case GE:
2698 return CC_FLAG_S;
2699 case GT:
2700 case LE:
2701 return CC_FLAG_S | CC_FLAG_O | CC_FLAG_Z;
2702 case GEU:
2703 case LTU:
2704 return CC_FLAG_C;
2705 case GTU:
2706 case LEU:
2707 return CC_FLAG_C | CC_FLAG_Z;
2708 case EQ:
2709 case NE:
2710 return CC_FLAG_Z;
2711 default:
2712 gcc_unreachable ();
2713 }
2714 }
2715
2716 /* Return a CC_MODE of which both M1 and M2 are subsets. */
2717
2718 static enum machine_mode
2719 rx_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
2720 {
2721 unsigned f;
2722
2723 /* Early out for identical modes. */
2724 if (m1 == m2)
2725 return m1;
2726
2727 /* There's no valid combination for FP vs non-FP. */
2728 f = flags_from_mode (m1) | flags_from_mode (m2);
2729 if (f & CC_FLAG_FP)
2730 return VOIDmode;
2731
2732 /* Otherwise, see what mode can implement all the flags. */
2733 return mode_from_flags (f);
2734 }
2735
2736 /* Return the minimal CC mode needed to implement (CMP_CODE X Y). */
2737
2738 enum machine_mode
2739 rx_select_cc_mode (enum rtx_code cmp_code, rtx x, rtx y)
2740 {
2741 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
2742 return CC_Fmode;
2743
2744 if (y != const0_rtx)
2745 return CCmode;
2746
2747 return mode_from_flags (flags_from_code (cmp_code));
2748 }
2749
2750 /* Split the conditional branch. Emit (COMPARE C1 C2) into CC_REG with
2751 CC_MODE, and use that in branches based on that compare. */
2752
2753 void
2754 rx_split_cbranch (enum machine_mode cc_mode, enum rtx_code cmp1,
2755 rtx c1, rtx c2, rtx label)
2756 {
2757 rtx flags, x;
2758
2759 flags = gen_rtx_REG (cc_mode, CC_REG);
2760 x = gen_rtx_COMPARE (cc_mode, c1, c2);
2761 x = gen_rtx_SET (VOIDmode, flags, x);
2762 emit_insn (x);
2763
2764 x = gen_rtx_fmt_ee (cmp1, VOIDmode, flags, const0_rtx);
2765 x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label, pc_rtx);
2766 x = gen_rtx_SET (VOIDmode, pc_rtx, x);
2767 emit_jump_insn (x);
2768 }
2769
2770 /* A helper function for matching parallels that set the flags. */
2771
2772 bool
2773 rx_match_ccmode (rtx insn, enum machine_mode cc_mode)
2774 {
2775 rtx op1, flags;
2776 enum machine_mode flags_mode;
2777
2778 gcc_checking_assert (XVECLEN (PATTERN (insn), 0) == 2);
2779
2780 op1 = XVECEXP (PATTERN (insn), 0, 1);
2781 gcc_checking_assert (GET_CODE (SET_SRC (op1)) == COMPARE);
2782
2783 flags = SET_DEST (op1);
2784 flags_mode = GET_MODE (flags);
2785
2786 if (GET_MODE (SET_SRC (op1)) != flags_mode)
2787 return false;
2788 if (GET_MODE_CLASS (flags_mode) != MODE_CC)
2789 return false;
2790
2791 /* Ensure that the mode of FLAGS is compatible with CC_MODE. */
2792 if (flags_from_mode (flags_mode) & ~flags_from_mode (cc_mode))
2793 return false;
2794
2795 return true;
2796 }
2797 \f
2798 int
2799 rx_align_for_label (rtx lab, int uses_threshold)
2800 {
2801 /* This is a simple heuristic to guess when an alignment would not be useful
2802 because the delay due to the inserted NOPs would be greater than the delay
2803 due to the misaligned branch. If uses_threshold is zero then the alignment
2804 is always useful. */
2805 if (LABEL_P (lab) && LABEL_NUSES (lab) < uses_threshold)
2806 return 0;
2807
2808 return optimize_size ? 1 : 3;
2809 }
2810
2811 static int
2812 rx_max_skip_for_label (rtx lab)
2813 {
2814 int opsize;
2815 rtx op;
2816
2817 if (lab == NULL_RTX)
2818 return 0;
2819
2820 op = lab;
2821 do
2822 {
2823 op = next_nonnote_nondebug_insn (op);
2824 }
2825 while (op && (LABEL_P (op)
2826 || (INSN_P (op) && GET_CODE (PATTERN (op)) == USE)));
2827 if (!op)
2828 return 0;
2829
2830 opsize = get_attr_length (op);
2831 if (opsize >= 0 && opsize < 8)
2832 return opsize - 1;
2833 return 0;
2834 }
2835
2836 /* Compute the real length of the extending load-and-op instructions. */
2837
2838 int
2839 rx_adjust_insn_length (rtx insn, int current_length)
2840 {
2841 rtx extend, mem, offset;
2842 bool zero;
2843 int factor;
2844
2845 switch (INSN_CODE (insn))
2846 {
2847 default:
2848 return current_length;
2849
2850 case CODE_FOR_plussi3_zero_extendhi:
2851 case CODE_FOR_andsi3_zero_extendhi:
2852 case CODE_FOR_iorsi3_zero_extendhi:
2853 case CODE_FOR_xorsi3_zero_extendhi:
2854 case CODE_FOR_divsi3_zero_extendhi:
2855 case CODE_FOR_udivsi3_zero_extendhi:
2856 case CODE_FOR_minussi3_zero_extendhi:
2857 case CODE_FOR_smaxsi3_zero_extendhi:
2858 case CODE_FOR_sminsi3_zero_extendhi:
2859 case CODE_FOR_multsi3_zero_extendhi:
2860 case CODE_FOR_comparesi3_zero_extendhi:
2861 zero = true;
2862 factor = 2;
2863 break;
2864
2865 case CODE_FOR_plussi3_sign_extendhi:
2866 case CODE_FOR_andsi3_sign_extendhi:
2867 case CODE_FOR_iorsi3_sign_extendhi:
2868 case CODE_FOR_xorsi3_sign_extendhi:
2869 case CODE_FOR_divsi3_sign_extendhi:
2870 case CODE_FOR_udivsi3_sign_extendhi:
2871 case CODE_FOR_minussi3_sign_extendhi:
2872 case CODE_FOR_smaxsi3_sign_extendhi:
2873 case CODE_FOR_sminsi3_sign_extendhi:
2874 case CODE_FOR_multsi3_sign_extendhi:
2875 case CODE_FOR_comparesi3_sign_extendhi:
2876 zero = false;
2877 factor = 2;
2878 break;
2879
2880 case CODE_FOR_plussi3_zero_extendqi:
2881 case CODE_FOR_andsi3_zero_extendqi:
2882 case CODE_FOR_iorsi3_zero_extendqi:
2883 case CODE_FOR_xorsi3_zero_extendqi:
2884 case CODE_FOR_divsi3_zero_extendqi:
2885 case CODE_FOR_udivsi3_zero_extendqi:
2886 case CODE_FOR_minussi3_zero_extendqi:
2887 case CODE_FOR_smaxsi3_zero_extendqi:
2888 case CODE_FOR_sminsi3_zero_extendqi:
2889 case CODE_FOR_multsi3_zero_extendqi:
2890 case CODE_FOR_comparesi3_zero_extendqi:
2891 zero = true;
2892 factor = 1;
2893 break;
2894
2895 case CODE_FOR_plussi3_sign_extendqi:
2896 case CODE_FOR_andsi3_sign_extendqi:
2897 case CODE_FOR_iorsi3_sign_extendqi:
2898 case CODE_FOR_xorsi3_sign_extendqi:
2899 case CODE_FOR_divsi3_sign_extendqi:
2900 case CODE_FOR_udivsi3_sign_extendqi:
2901 case CODE_FOR_minussi3_sign_extendqi:
2902 case CODE_FOR_smaxsi3_sign_extendqi:
2903 case CODE_FOR_sminsi3_sign_extendqi:
2904 case CODE_FOR_multsi3_sign_extendqi:
2905 case CODE_FOR_comparesi3_sign_extendqi:
2906 zero = false;
2907 factor = 1;
2908 break;
2909 }
2910
2911 /* We are expecting: (SET (REG) (<OP> (REG) (<EXTEND> (MEM)))). */
2912 extend = single_set (insn);
2913 gcc_assert (extend != NULL_RTX);
2914
2915 extend = SET_SRC (extend);
2916 if (GET_CODE (XEXP (extend, 0)) == ZERO_EXTEND
2917 || GET_CODE (XEXP (extend, 0)) == SIGN_EXTEND)
2918 extend = XEXP (extend, 0);
2919 else
2920 extend = XEXP (extend, 1);
2921
2922 gcc_assert ((zero && (GET_CODE (extend) == ZERO_EXTEND))
2923 || (! zero && (GET_CODE (extend) == SIGN_EXTEND)));
2924
2925 mem = XEXP (extend, 0);
2926 gcc_checking_assert (MEM_P (mem));
2927 if (REG_P (XEXP (mem, 0)))
2928 return (zero && factor == 1) ? 2 : 3;
2929
2930 /* We are expecting: (MEM (PLUS (REG) (CONST_INT))). */
2931 gcc_checking_assert (GET_CODE (XEXP (mem, 0)) == PLUS);
2932 gcc_checking_assert (REG_P (XEXP (XEXP (mem, 0), 0)));
2933
2934 offset = XEXP (XEXP (mem, 0), 1);
2935 gcc_checking_assert (GET_CODE (offset) == CONST_INT);
2936
2937 if (IN_RANGE (INTVAL (offset), 0, 255 * factor))
2938 return (zero && factor == 1) ? 3 : 4;
2939
2940 return (zero && factor == 1) ? 4 : 5;
2941 }
2942 \f
2943 #undef TARGET_ASM_JUMP_ALIGN_MAX_SKIP
2944 #define TARGET_ASM_JUMP_ALIGN_MAX_SKIP rx_max_skip_for_label
2945 #undef TARGET_ASM_LOOP_ALIGN_MAX_SKIP
2946 #define TARGET_ASM_LOOP_ALIGN_MAX_SKIP rx_max_skip_for_label
2947 #undef TARGET_LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP
2948 #define TARGET_LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP rx_max_skip_for_label
2949 #undef TARGET_ASM_LABEL_ALIGN_MAX_SKIP
2950 #define TARGET_ASM_LABEL_ALIGN_MAX_SKIP rx_max_skip_for_label
2951
2952 #undef TARGET_FUNCTION_VALUE
2953 #define TARGET_FUNCTION_VALUE rx_function_value
2954
2955 #undef TARGET_RETURN_IN_MSB
2956 #define TARGET_RETURN_IN_MSB rx_return_in_msb
2957
2958 #undef TARGET_IN_SMALL_DATA_P
2959 #define TARGET_IN_SMALL_DATA_P rx_in_small_data
2960
2961 #undef TARGET_RETURN_IN_MEMORY
2962 #define TARGET_RETURN_IN_MEMORY rx_return_in_memory
2963
2964 #undef TARGET_HAVE_SRODATA_SECTION
2965 #define TARGET_HAVE_SRODATA_SECTION true
2966
2967 #undef TARGET_ASM_SELECT_RTX_SECTION
2968 #define TARGET_ASM_SELECT_RTX_SECTION rx_select_rtx_section
2969
2970 #undef TARGET_ASM_SELECT_SECTION
2971 #define TARGET_ASM_SELECT_SECTION rx_select_section
2972
2973 #undef TARGET_INIT_BUILTINS
2974 #define TARGET_INIT_BUILTINS rx_init_builtins
2975
2976 #undef TARGET_BUILTIN_DECL
2977 #define TARGET_BUILTIN_DECL rx_builtin_decl
2978
2979 #undef TARGET_EXPAND_BUILTIN
2980 #define TARGET_EXPAND_BUILTIN rx_expand_builtin
2981
2982 #undef TARGET_ASM_CONSTRUCTOR
2983 #define TARGET_ASM_CONSTRUCTOR rx_elf_asm_constructor
2984
2985 #undef TARGET_ASM_DESTRUCTOR
2986 #define TARGET_ASM_DESTRUCTOR rx_elf_asm_destructor
2987
2988 #undef TARGET_STRUCT_VALUE_RTX
2989 #define TARGET_STRUCT_VALUE_RTX rx_struct_value_rtx
2990
2991 #undef TARGET_ATTRIBUTE_TABLE
2992 #define TARGET_ATTRIBUTE_TABLE rx_attribute_table
2993
2994 #undef TARGET_ASM_FILE_START
2995 #define TARGET_ASM_FILE_START rx_file_start
2996
2997 #undef TARGET_MS_BITFIELD_LAYOUT_P
2998 #define TARGET_MS_BITFIELD_LAYOUT_P rx_is_ms_bitfield_layout
2999
3000 #undef TARGET_LEGITIMATE_ADDRESS_P
3001 #define TARGET_LEGITIMATE_ADDRESS_P rx_is_legitimate_address
3002
3003 #undef TARGET_MODE_DEPENDENT_ADDRESS_P
3004 #define TARGET_MODE_DEPENDENT_ADDRESS_P rx_mode_dependent_address_p
3005
3006 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
3007 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS rx_allocate_stack_slots_for_args
3008
3009 #undef TARGET_ASM_FUNCTION_PROLOGUE
3010 #define TARGET_ASM_FUNCTION_PROLOGUE rx_output_function_prologue
3011
3012 #undef TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P
3013 #define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P rx_func_attr_inlinable
3014
3015 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
3016 #define TARGET_FUNCTION_OK_FOR_SIBCALL rx_function_ok_for_sibcall
3017
3018 #undef TARGET_FUNCTION_ARG
3019 #define TARGET_FUNCTION_ARG rx_function_arg
3020
3021 #undef TARGET_FUNCTION_ARG_ADVANCE
3022 #define TARGET_FUNCTION_ARG_ADVANCE rx_function_arg_advance
3023
3024 #undef TARGET_FUNCTION_ARG_BOUNDARY
3025 #define TARGET_FUNCTION_ARG_BOUNDARY rx_function_arg_boundary
3026
3027 #undef TARGET_SET_CURRENT_FUNCTION
3028 #define TARGET_SET_CURRENT_FUNCTION rx_set_current_function
3029
3030 #undef TARGET_HANDLE_OPTION
3031 #define TARGET_HANDLE_OPTION rx_handle_option
3032
3033 #undef TARGET_ASM_INTEGER
3034 #define TARGET_ASM_INTEGER rx_assemble_integer
3035
3036 #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
3037 #define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_true
3038
3039 #undef TARGET_MAX_ANCHOR_OFFSET
3040 #define TARGET_MAX_ANCHOR_OFFSET 32
3041
3042 #undef TARGET_ADDRESS_COST
3043 #define TARGET_ADDRESS_COST rx_address_cost
3044
3045 #undef TARGET_CAN_ELIMINATE
3046 #define TARGET_CAN_ELIMINATE rx_can_eliminate
3047
3048 #undef TARGET_CONDITIONAL_REGISTER_USAGE
3049 #define TARGET_CONDITIONAL_REGISTER_USAGE rx_conditional_register_usage
3050
3051 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
3052 #define TARGET_ASM_TRAMPOLINE_TEMPLATE rx_trampoline_template
3053
3054 #undef TARGET_TRAMPOLINE_INIT
3055 #define TARGET_TRAMPOLINE_INIT rx_trampoline_init
3056
3057 #undef TARGET_PRINT_OPERAND
3058 #define TARGET_PRINT_OPERAND rx_print_operand
3059
3060 #undef TARGET_PRINT_OPERAND_ADDRESS
3061 #define TARGET_PRINT_OPERAND_ADDRESS rx_print_operand_address
3062
3063 #undef TARGET_CC_MODES_COMPATIBLE
3064 #define TARGET_CC_MODES_COMPATIBLE rx_cc_modes_compatible
3065
3066 #undef TARGET_MEMORY_MOVE_COST
3067 #define TARGET_MEMORY_MOVE_COST rx_memory_move_cost
3068
3069 #undef TARGET_OPTION_OVERRIDE
3070 #define TARGET_OPTION_OVERRIDE rx_option_override
3071
3072 #undef TARGET_OPTION_OPTIMIZATION_TABLE
3073 #define TARGET_OPTION_OPTIMIZATION_TABLE rx_option_optimization_table
3074
3075 #undef TARGET_PROMOTE_FUNCTION_MODE
3076 #define TARGET_PROMOTE_FUNCTION_MODE rx_promote_function_mode
3077
3078 #undef TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE
3079 #define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE rx_override_options_after_change
3080
3081 #undef TARGET_EXCEPT_UNWIND_INFO
3082 #define TARGET_EXCEPT_UNWIND_INFO sjlj_except_unwind_info
3083
3084 #undef TARGET_FLAGS_REGNUM
3085 #define TARGET_FLAGS_REGNUM CC_REG
3086
3087 #undef TARGET_LEGITIMATE_CONSTANT_P
3088 #define TARGET_LEGITIMATE_CONSTANT_P rx_is_legitimate_constant
3089
3090 struct gcc_target targetm = TARGET_INITIALIZER;
3091
3092 #include "gt-rx.h"