* gengenrtl.c (special_rtx): PC, CC0 and RETURN are special.
[official-gcc.git] / gcc / config / rx / rx.c
blobccf1a5d11b96c359e85bd62930389a7884b9b1fa
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.
5 This file is part of GCC.
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.
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.
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/>. */
21 /* To Do:
23 * Re-enable memory-to-memory copies and fix up reload. */
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"
55 static void rx_print_operand (FILE *, rtx, int);
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 */
63 static unsigned int flags_from_mode (enum machine_mode mode);
64 static unsigned int flags_from_code (enum rtx_code code);
66 /* Return true if OP is a reference to an object in a small data area. */
68 static bool
69 rx_small_data_operand (rtx op)
71 if (rx_small_data_limit == 0)
72 return false;
74 if (GET_CODE (op) == SYMBOL_REF)
75 return SYMBOL_REF_SMALL_P (op);
77 return false;
80 static bool
81 rx_is_legitimate_address (enum machine_mode mode, rtx x,
82 bool strict ATTRIBUTE_UNUSED)
84 if (RTX_OK_FOR_BASE (x, strict))
85 /* Register Indirect. */
86 return true;
88 if (GET_MODE_SIZE (mode) <= 4
89 && (GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC))
90 /* Pre-decrement Register Indirect or
91 Post-increment Register Indirect. */
92 return RTX_OK_FOR_BASE (XEXP (x, 0), strict);
94 if (GET_CODE (x) == PLUS)
96 rtx arg1 = XEXP (x, 0);
97 rtx arg2 = XEXP (x, 1);
98 rtx index = NULL_RTX;
100 if (REG_P (arg1) && RTX_OK_FOR_BASE (arg1, strict))
101 index = arg2;
102 else if (REG_P (arg2) && RTX_OK_FOR_BASE (arg2, strict))
103 index = arg1;
104 else
105 return false;
107 switch (GET_CODE (index))
109 case CONST_INT:
111 /* Register Relative: REG + INT.
112 Only positive, mode-aligned, mode-sized
113 displacements are allowed. */
114 HOST_WIDE_INT val = INTVAL (index);
115 int factor;
117 if (val < 0)
118 return false;
120 switch (GET_MODE_SIZE (mode))
122 default:
123 case 4: factor = 4; break;
124 case 2: factor = 2; break;
125 case 1: factor = 1; break;
128 if (val >= (0x10000 * factor))
129 return false;
130 return (val % factor) == 0;
133 case REG:
134 /* Unscaled Indexed Register Indirect: REG + REG
135 Size has to be "QI", REG has to be valid. */
136 return GET_MODE_SIZE (mode) == 1 && RTX_OK_FOR_BASE (index, strict);
138 case MULT:
140 /* Scaled Indexed Register Indirect: REG + (REG * FACTOR)
141 Factor has to equal the mode size, REG has to be valid. */
142 rtx factor;
144 factor = XEXP (index, 1);
145 index = XEXP (index, 0);
147 return REG_P (index)
148 && RTX_OK_FOR_BASE (index, strict)
149 && CONST_INT_P (factor)
150 && GET_MODE_SIZE (mode) == INTVAL (factor);
153 default:
154 return false;
158 /* Small data area accesses turn into register relative offsets. */
159 return rx_small_data_operand (x);
162 /* Returns TRUE for simple memory addreses, ie ones
163 that do not involve register indirect addressing
164 or pre/post increment/decrement. */
166 bool
167 rx_is_restricted_memory_address (rtx mem, enum machine_mode mode)
169 if (! rx_is_legitimate_address
170 (mode, mem, reload_in_progress || reload_completed))
171 return false;
173 switch (GET_CODE (mem))
175 case REG:
176 /* Simple memory addresses are OK. */
177 return true;
179 case PRE_DEC:
180 case POST_INC:
181 return false;
183 case PLUS:
185 rtx base, index;
187 /* Only allow REG+INT addressing. */
188 base = XEXP (mem, 0);
189 index = XEXP (mem, 1);
191 if (! RX_REG_P (base) || ! CONST_INT_P (index))
192 return false;
194 return IN_RANGE (INTVAL (index), 0, (0x10000 * GET_MODE_SIZE (mode)) - 1);
197 case SYMBOL_REF:
198 /* Can happen when small data is being supported.
199 Assume that it will be resolved into GP+INT. */
200 return true;
202 default:
203 gcc_unreachable ();
207 /* Implement TARGET_MODE_DEPENDENT_ADDRESS_P. */
209 static bool
210 rx_mode_dependent_address_p (const_rtx addr)
212 if (GET_CODE (addr) == CONST)
213 addr = XEXP (addr, 0);
215 switch (GET_CODE (addr))
217 /* --REG and REG++ only work in SImode. */
218 case PRE_DEC:
219 case POST_INC:
220 return true;
222 case MINUS:
223 case PLUS:
224 if (! REG_P (XEXP (addr, 0)))
225 return true;
227 addr = XEXP (addr, 1);
229 switch (GET_CODE (addr))
231 case REG:
232 /* REG+REG only works in SImode. */
233 return true;
235 case CONST_INT:
236 /* REG+INT is only mode independent if INT is a
237 multiple of 4, positive and will fit into 8-bits. */
238 if (((INTVAL (addr) & 3) == 0)
239 && IN_RANGE (INTVAL (addr), 4, 252))
240 return false;
241 return true;
243 case SYMBOL_REF:
244 case LABEL_REF:
245 return true;
247 case MULT:
248 gcc_assert (REG_P (XEXP (addr, 0)));
249 gcc_assert (CONST_INT_P (XEXP (addr, 1)));
250 /* REG+REG*SCALE is always mode dependent. */
251 return true;
253 default:
254 /* Not recognized, so treat as mode dependent. */
255 return true;
258 case CONST_INT:
259 case SYMBOL_REF:
260 case LABEL_REF:
261 case REG:
262 /* These are all mode independent. */
263 return false;
265 default:
266 /* Everything else is unrecognized,
267 so treat as mode dependent. */
268 return true;
272 /* A C compound statement to output to stdio stream FILE the
273 assembler syntax for an instruction operand that is a memory
274 reference whose address is ADDR. */
276 static void
277 rx_print_operand_address (FILE * file, rtx addr)
279 switch (GET_CODE (addr))
281 case REG:
282 fprintf (file, "[");
283 rx_print_operand (file, addr, 0);
284 fprintf (file, "]");
285 break;
287 case PRE_DEC:
288 fprintf (file, "[-");
289 rx_print_operand (file, XEXP (addr, 0), 0);
290 fprintf (file, "]");
291 break;
293 case POST_INC:
294 fprintf (file, "[");
295 rx_print_operand (file, XEXP (addr, 0), 0);
296 fprintf (file, "+]");
297 break;
299 case PLUS:
301 rtx arg1 = XEXP (addr, 0);
302 rtx arg2 = XEXP (addr, 1);
303 rtx base, index;
305 if (REG_P (arg1) && RTX_OK_FOR_BASE (arg1, true))
306 base = arg1, index = arg2;
307 else if (REG_P (arg2) && RTX_OK_FOR_BASE (arg2, true))
308 base = arg2, index = arg1;
309 else
311 rx_print_operand (file, arg1, 0);
312 fprintf (file, " + ");
313 rx_print_operand (file, arg2, 0);
314 break;
317 if (REG_P (index) || GET_CODE (index) == MULT)
319 fprintf (file, "[");
320 rx_print_operand (file, index, 'A');
321 fprintf (file, ",");
323 else /* GET_CODE (index) == CONST_INT */
325 rx_print_operand (file, index, 'A');
326 fprintf (file, "[");
328 rx_print_operand (file, base, 0);
329 fprintf (file, "]");
330 break;
333 case CONST:
334 if (GET_CODE (XEXP (addr, 0)) == UNSPEC)
336 addr = XEXP (addr, 0);
337 gcc_assert (XINT (addr, 1) == UNSPEC_CONST);
339 addr = XVECEXP (addr, 0, 0);
340 gcc_assert (CONST_INT_P (addr));
342 /* Fall through. */
343 case LABEL_REF:
344 case SYMBOL_REF:
345 fprintf (file, "#");
347 default:
348 output_addr_const (file, addr);
349 break;
353 static void
354 rx_print_integer (FILE * file, HOST_WIDE_INT val)
356 if (IN_RANGE (val, -64, 64))
357 fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
358 else
359 fprintf (file,
360 TARGET_AS100_SYNTAX
361 ? "0%" HOST_WIDE_INT_PRINT "xH" : HOST_WIDE_INT_PRINT_HEX,
362 val);
365 static bool
366 rx_assemble_integer (rtx x, unsigned int size, int is_aligned)
368 const char * op = integer_asm_op (size, is_aligned);
370 if (! CONST_INT_P (x))
371 return default_assemble_integer (x, size, is_aligned);
373 if (op == NULL)
374 return false;
375 fputs (op, asm_out_file);
377 rx_print_integer (asm_out_file, INTVAL (x));
378 fputc ('\n', asm_out_file);
379 return true;
383 /* Handles the insertion of a single operand into the assembler output.
384 The %<letter> directives supported are:
386 %A Print an operand without a leading # character.
387 %B Print an integer comparison name.
388 %C Print a control register name.
389 %F Print a condition code flag name.
390 %H Print high part of a DImode register, integer or address.
391 %L Print low part of a DImode register, integer or address.
392 %N Print the negation of the immediate value.
393 %Q If the operand is a MEM, then correctly generate
394 register indirect or register relative addressing.
395 %R Like %Q but for zero-extending loads. */
397 static void
398 rx_print_operand (FILE * file, rtx op, int letter)
400 bool unsigned_load = false;
402 switch (letter)
404 case 'A':
405 /* Print an operand without a leading #. */
406 if (MEM_P (op))
407 op = XEXP (op, 0);
409 switch (GET_CODE (op))
411 case LABEL_REF:
412 case SYMBOL_REF:
413 output_addr_const (file, op);
414 break;
415 case CONST_INT:
416 fprintf (file, "%ld", (long) INTVAL (op));
417 break;
418 default:
419 rx_print_operand (file, op, 0);
420 break;
422 break;
424 case 'B':
426 enum rtx_code code = GET_CODE (op);
427 enum machine_mode mode = GET_MODE (XEXP (op, 0));
428 const char *ret;
430 if (mode == CC_Fmode)
432 /* C flag is undefined, and O flag carries unordered. None of the
433 branch combinations that include O use it helpfully. */
434 switch (code)
436 case ORDERED:
437 ret = "no";
438 break;
439 case UNORDERED:
440 ret = "o";
441 break;
442 case LT:
443 ret = "n";
444 break;
445 case GE:
446 ret = "pz";
447 break;
448 case EQ:
449 ret = "eq";
450 break;
451 case NE:
452 ret = "ne";
453 break;
454 default:
455 gcc_unreachable ();
458 else
460 unsigned int flags = flags_from_mode (mode);
462 switch (code)
464 case LT:
465 ret = (flags & CC_FLAG_O ? "lt" : "n");
466 break;
467 case GE:
468 ret = (flags & CC_FLAG_O ? "ge" : "pz");
469 break;
470 case GT:
471 ret = "gt";
472 break;
473 case LE:
474 ret = "le";
475 break;
476 case GEU:
477 ret = "geu";
478 break;
479 case LTU:
480 ret = "ltu";
481 break;
482 case GTU:
483 ret = "gtu";
484 break;
485 case LEU:
486 ret = "leu";
487 break;
488 case EQ:
489 ret = "eq";
490 break;
491 case NE:
492 ret = "ne";
493 break;
494 default:
495 gcc_unreachable ();
497 gcc_checking_assert ((flags_from_code (code) & ~flags) == 0);
499 fputs (ret, file);
500 break;
503 case 'C':
504 gcc_assert (CONST_INT_P (op));
505 switch (INTVAL (op))
507 case 0: fprintf (file, "psw"); break;
508 case 2: fprintf (file, "usp"); break;
509 case 3: fprintf (file, "fpsw"); break;
510 case 4: fprintf (file, "cpen"); break;
511 case 8: fprintf (file, "bpsw"); break;
512 case 9: fprintf (file, "bpc"); break;
513 case 0xa: fprintf (file, "isp"); break;
514 case 0xb: fprintf (file, "fintv"); break;
515 case 0xc: fprintf (file, "intb"); break;
516 default:
517 warning (0, "unreocgnized control register number: %d - using 'psw'",
518 (int) INTVAL (op));
519 fprintf (file, "psw");
520 break;
522 break;
524 case 'F':
525 gcc_assert (CONST_INT_P (op));
526 switch (INTVAL (op))
528 case 0: case 'c': case 'C': fprintf (file, "C"); break;
529 case 1: case 'z': case 'Z': fprintf (file, "Z"); break;
530 case 2: case 's': case 'S': fprintf (file, "S"); break;
531 case 3: case 'o': case 'O': fprintf (file, "O"); break;
532 case 8: case 'i': case 'I': fprintf (file, "I"); break;
533 case 9: case 'u': case 'U': fprintf (file, "U"); break;
534 default:
535 gcc_unreachable ();
537 break;
539 case 'H':
540 switch (GET_CODE (op))
542 case REG:
543 fprintf (file, "%s", reg_names [REGNO (op) + (WORDS_BIG_ENDIAN ? 0 : 1)]);
544 break;
545 case CONST_INT:
547 HOST_WIDE_INT v = INTVAL (op);
549 fprintf (file, "#");
550 /* Trickery to avoid problems with shifting 32 bits at a time. */
551 v = v >> 16;
552 v = v >> 16;
553 rx_print_integer (file, v);
554 break;
556 case CONST_DOUBLE:
557 fprintf (file, "#");
558 rx_print_integer (file, CONST_DOUBLE_HIGH (op));
559 break;
560 case MEM:
561 if (! WORDS_BIG_ENDIAN)
562 op = adjust_address (op, SImode, 4);
563 output_address (XEXP (op, 0));
564 break;
565 default:
566 gcc_unreachable ();
568 break;
570 case 'L':
571 switch (GET_CODE (op))
573 case REG:
574 fprintf (file, "%s", reg_names [REGNO (op) + (WORDS_BIG_ENDIAN ? 1 : 0)]);
575 break;
576 case CONST_INT:
577 fprintf (file, "#");
578 rx_print_integer (file, INTVAL (op) & 0xffffffff);
579 break;
580 case CONST_DOUBLE:
581 fprintf (file, "#");
582 rx_print_integer (file, CONST_DOUBLE_LOW (op));
583 break;
584 case MEM:
585 if (WORDS_BIG_ENDIAN)
586 op = adjust_address (op, SImode, 4);
587 output_address (XEXP (op, 0));
588 break;
589 default:
590 gcc_unreachable ();
592 break;
594 case 'N':
595 gcc_assert (CONST_INT_P (op));
596 fprintf (file, "#");
597 rx_print_integer (file, - INTVAL (op));
598 break;
600 case 'R':
601 gcc_assert (GET_MODE_SIZE (GET_MODE (op)) < 4);
602 unsigned_load = true;
603 /* Fall through. */
604 case 'Q':
605 if (MEM_P (op))
607 HOST_WIDE_INT offset;
608 rtx mem = op;
610 op = XEXP (op, 0);
612 if (REG_P (op))
613 offset = 0;
614 else if (GET_CODE (op) == PLUS)
616 rtx displacement;
618 if (REG_P (XEXP (op, 0)))
620 displacement = XEXP (op, 1);
621 op = XEXP (op, 0);
623 else
625 displacement = XEXP (op, 0);
626 op = XEXP (op, 1);
627 gcc_assert (REG_P (op));
630 gcc_assert (CONST_INT_P (displacement));
631 offset = INTVAL (displacement);
632 gcc_assert (offset >= 0);
634 fprintf (file, "%ld", offset);
636 else
637 gcc_unreachable ();
639 fprintf (file, "[");
640 rx_print_operand (file, op, 0);
641 fprintf (file, "].");
643 switch (GET_MODE_SIZE (GET_MODE (mem)))
645 case 1:
646 gcc_assert (offset <= 65535 * 1);
647 fprintf (file, unsigned_load ? "UB" : "B");
648 break;
649 case 2:
650 gcc_assert (offset % 2 == 0);
651 gcc_assert (offset <= 65535 * 2);
652 fprintf (file, unsigned_load ? "UW" : "W");
653 break;
654 case 4:
655 gcc_assert (offset % 4 == 0);
656 gcc_assert (offset <= 65535 * 4);
657 fprintf (file, "L");
658 break;
659 default:
660 gcc_unreachable ();
662 break;
665 /* Fall through. */
667 default:
668 switch (GET_CODE (op))
670 case MULT:
671 /* Should be the scaled part of an
672 indexed register indirect address. */
674 rtx base = XEXP (op, 0);
675 rtx index = XEXP (op, 1);
677 /* Check for a swaped index register and scaling factor.
678 Not sure if this can happen, but be prepared to handle it. */
679 if (CONST_INT_P (base) && REG_P (index))
681 rtx tmp = base;
682 base = index;
683 index = tmp;
686 gcc_assert (REG_P (base));
687 gcc_assert (REGNO (base) < FIRST_PSEUDO_REGISTER);
688 gcc_assert (CONST_INT_P (index));
689 /* Do not try to verify the value of the scalar as it is based
690 on the mode of the MEM not the mode of the MULT. (Which
691 will always be SImode). */
692 fprintf (file, "%s", reg_names [REGNO (base)]);
693 break;
696 case MEM:
697 output_address (XEXP (op, 0));
698 break;
700 case PLUS:
701 output_address (op);
702 break;
704 case REG:
705 gcc_assert (REGNO (op) < FIRST_PSEUDO_REGISTER);
706 fprintf (file, "%s", reg_names [REGNO (op)]);
707 break;
709 case SUBREG:
710 gcc_assert (subreg_regno (op) < FIRST_PSEUDO_REGISTER);
711 fprintf (file, "%s", reg_names [subreg_regno (op)]);
712 break;
714 /* This will only be single precision.... */
715 case CONST_DOUBLE:
717 unsigned long val;
718 REAL_VALUE_TYPE rv;
720 REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
721 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
722 fprintf (file, TARGET_AS100_SYNTAX ? "#0%lxH" : "#0x%lx", val);
723 break;
726 case CONST_INT:
727 fprintf (file, "#");
728 rx_print_integer (file, INTVAL (op));
729 break;
731 case SYMBOL_REF:
732 case CONST:
733 case LABEL_REF:
734 case CODE_LABEL:
735 case UNSPEC:
736 rx_print_operand_address (file, op);
737 break;
739 default:
740 gcc_unreachable ();
742 break;
746 /* Returns an assembler template for a move instruction. */
748 char *
749 rx_gen_move_template (rtx * operands, bool is_movu)
751 static char out_template [64];
752 const char * extension = TARGET_AS100_SYNTAX ? ".L" : "";
753 const char * src_template;
754 const char * dst_template;
755 rtx dest = operands[0];
756 rtx src = operands[1];
758 /* Decide which extension, if any, should be given to the move instruction. */
759 switch (CONST_INT_P (src) ? GET_MODE (dest) : GET_MODE (src))
761 case QImode:
762 /* The .B extension is not valid when
763 loading an immediate into a register. */
764 if (! REG_P (dest) || ! CONST_INT_P (src))
765 extension = ".B";
766 break;
767 case HImode:
768 if (! REG_P (dest) || ! CONST_INT_P (src))
769 /* The .W extension is not valid when
770 loading an immediate into a register. */
771 extension = ".W";
772 break;
773 case SFmode:
774 case SImode:
775 extension = ".L";
776 break;
777 case VOIDmode:
778 /* This mode is used by constants. */
779 break;
780 default:
781 debug_rtx (src);
782 gcc_unreachable ();
785 if (MEM_P (src) && rx_small_data_operand (XEXP (src, 0)))
786 src_template = "%%gp(%A1)[r13]";
787 else
788 src_template = "%1";
790 if (MEM_P (dest) && rx_small_data_operand (XEXP (dest, 0)))
791 dst_template = "%%gp(%A0)[r13]";
792 else
793 dst_template = "%0";
795 sprintf (out_template, "%s%s\t%s, %s", is_movu ? "movu" : "mov",
796 extension, src_template, dst_template);
797 return out_template;
800 /* Return VALUE rounded up to the next ALIGNMENT boundary. */
802 static inline unsigned int
803 rx_round_up (unsigned int value, unsigned int alignment)
805 alignment -= 1;
806 return (value + alignment) & (~ alignment);
809 /* Return the number of bytes in the argument registers
810 occupied by an argument of type TYPE and mode MODE. */
812 static unsigned int
813 rx_function_arg_size (enum machine_mode mode, const_tree type)
815 unsigned int num_bytes;
817 num_bytes = (mode == BLKmode)
818 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
819 return rx_round_up (num_bytes, UNITS_PER_WORD);
822 #define NUM_ARG_REGS 4
823 #define MAX_NUM_ARG_BYTES (NUM_ARG_REGS * UNITS_PER_WORD)
825 /* Return an RTL expression describing the register holding a function
826 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
827 be passed on the stack. CUM describes the previous parameters to the
828 function and NAMED is false if the parameter is part of a variable
829 parameter list, or the last named parameter before the start of a
830 variable parameter list. */
832 static rtx
833 rx_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode,
834 const_tree type, bool named)
836 unsigned int next_reg;
837 unsigned int bytes_so_far = *cum;
838 unsigned int size;
839 unsigned int rounded_size;
841 /* An exploded version of rx_function_arg_size. */
842 size = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
843 /* If the size is not known it cannot be passed in registers. */
844 if (size < 1)
845 return NULL_RTX;
847 rounded_size = rx_round_up (size, UNITS_PER_WORD);
849 /* Don't pass this arg via registers if there
850 are insufficient registers to hold all of it. */
851 if (rounded_size + bytes_so_far > MAX_NUM_ARG_BYTES)
852 return NULL_RTX;
854 /* Unnamed arguments and the last named argument in a
855 variadic function are always passed on the stack. */
856 if (!named)
857 return NULL_RTX;
859 /* Structures must occupy an exact number of registers,
860 otherwise they are passed on the stack. */
861 if ((type == NULL || AGGREGATE_TYPE_P (type))
862 && (size % UNITS_PER_WORD) != 0)
863 return NULL_RTX;
865 next_reg = (bytes_so_far / UNITS_PER_WORD) + 1;
867 return gen_rtx_REG (mode, next_reg);
870 static void
871 rx_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode,
872 const_tree type, bool named ATTRIBUTE_UNUSED)
874 *cum += rx_function_arg_size (mode, type);
877 static unsigned int
878 rx_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
879 const_tree type ATTRIBUTE_UNUSED)
881 return 32;
884 /* Return an RTL describing where a function return value of type RET_TYPE
885 is held. */
887 static rtx
888 rx_function_value (const_tree ret_type,
889 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
890 bool outgoing ATTRIBUTE_UNUSED)
892 enum machine_mode mode = TYPE_MODE (ret_type);
894 /* RX ABI specifies that small integer types are
895 promoted to int when returned by a function. */
896 if (GET_MODE_SIZE (mode) > 0
897 && GET_MODE_SIZE (mode) < 4
898 && ! COMPLEX_MODE_P (mode)
900 return gen_rtx_REG (SImode, FUNC_RETURN_REGNUM);
902 return gen_rtx_REG (mode, FUNC_RETURN_REGNUM);
905 /* TARGET_PROMOTE_FUNCTION_MODE must behave in the same way with
906 regard to function returns as does TARGET_FUNCTION_VALUE. */
908 static enum machine_mode
909 rx_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
910 enum machine_mode mode,
911 int * punsignedp ATTRIBUTE_UNUSED,
912 const_tree funtype ATTRIBUTE_UNUSED,
913 int for_return)
915 if (for_return != 1
916 || GET_MODE_SIZE (mode) >= 4
917 || COMPLEX_MODE_P (mode)
918 || GET_MODE_SIZE (mode) < 1)
919 return mode;
921 return SImode;
924 static bool
925 rx_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
927 HOST_WIDE_INT size;
929 if (TYPE_MODE (type) != BLKmode
930 && ! AGGREGATE_TYPE_P (type))
931 return false;
933 size = int_size_in_bytes (type);
934 /* Large structs and those whose size is not an
935 exact multiple of 4 are returned in memory. */
936 return size < 1
937 || size > 16
938 || (size % UNITS_PER_WORD) != 0;
941 static rtx
942 rx_struct_value_rtx (tree fndecl ATTRIBUTE_UNUSED,
943 int incoming ATTRIBUTE_UNUSED)
945 return gen_rtx_REG (Pmode, STRUCT_VAL_REGNUM);
948 static bool
949 rx_return_in_msb (const_tree valtype)
951 return TARGET_BIG_ENDIAN_DATA
952 && (AGGREGATE_TYPE_P (valtype) || TREE_CODE (valtype) == COMPLEX_TYPE);
955 /* Returns true if the provided function has the specified attribute. */
957 static inline bool
958 has_func_attr (const_tree decl, const char * func_attr)
960 if (decl == NULL_TREE)
961 decl = current_function_decl;
963 return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
966 /* Returns true if the provided function has the "fast_interrupt" attribute. */
968 static inline bool
969 is_fast_interrupt_func (const_tree decl)
971 return has_func_attr (decl, "fast_interrupt");
974 /* Returns true if the provided function has the "interrupt" attribute. */
976 static inline bool
977 is_interrupt_func (const_tree decl)
979 return has_func_attr (decl, "interrupt");
982 /* Returns true if the provided function has the "naked" attribute. */
984 static inline bool
985 is_naked_func (const_tree decl)
987 return has_func_attr (decl, "naked");
990 static bool use_fixed_regs = false;
992 static void
993 rx_conditional_register_usage (void)
995 static bool using_fixed_regs = false;
997 if (rx_small_data_limit > 0)
998 fixed_regs[GP_BASE_REGNUM] = call_used_regs [GP_BASE_REGNUM] = 1;
1000 if (use_fixed_regs != using_fixed_regs)
1002 static char saved_fixed_regs[FIRST_PSEUDO_REGISTER];
1003 static char saved_call_used_regs[FIRST_PSEUDO_REGISTER];
1005 if (use_fixed_regs)
1007 unsigned int r;
1009 memcpy (saved_fixed_regs, fixed_regs, sizeof fixed_regs);
1010 memcpy (saved_call_used_regs, call_used_regs, sizeof call_used_regs);
1012 /* This is for fast interrupt handlers. Any register in
1013 the range r10 to r13 (inclusive) that is currently
1014 marked as fixed is now a viable, call-used register. */
1015 for (r = 10; r <= 13; r++)
1016 if (fixed_regs[r])
1018 fixed_regs[r] = 0;
1019 call_used_regs[r] = 1;
1022 /* Mark r7 as fixed. This is just a hack to avoid
1023 altering the reg_alloc_order array so that the newly
1024 freed r10-r13 registers are the preferred registers. */
1025 fixed_regs[7] = call_used_regs[7] = 1;
1027 else
1029 /* Restore the normal register masks. */
1030 memcpy (fixed_regs, saved_fixed_regs, sizeof fixed_regs);
1031 memcpy (call_used_regs, saved_call_used_regs, sizeof call_used_regs);
1034 using_fixed_regs = use_fixed_regs;
1038 /* Perform any actions necessary before starting to compile FNDECL.
1039 For the RX we use this to make sure that we have the correct
1040 set of register masks selected. If FNDECL is NULL then we are
1041 compiling top level things. */
1043 static void
1044 rx_set_current_function (tree fndecl)
1046 /* Remember the last target of rx_set_current_function. */
1047 static tree rx_previous_fndecl;
1048 bool prev_was_fast_interrupt;
1049 bool current_is_fast_interrupt;
1051 /* Only change the context if the function changes. This hook is called
1052 several times in the course of compiling a function, and we don't want
1053 to slow things down too much or call target_reinit when it isn't safe. */
1054 if (fndecl == rx_previous_fndecl)
1055 return;
1057 prev_was_fast_interrupt
1058 = rx_previous_fndecl
1059 ? is_fast_interrupt_func (rx_previous_fndecl) : false;
1061 current_is_fast_interrupt
1062 = fndecl ? is_fast_interrupt_func (fndecl) : false;
1064 if (prev_was_fast_interrupt != current_is_fast_interrupt)
1066 use_fixed_regs = current_is_fast_interrupt;
1067 target_reinit ();
1070 rx_previous_fndecl = fndecl;
1073 /* Typical stack layout should looks like this after the function's prologue:
1076 -- ^
1077 | | \ |
1078 | | arguments saved | Increasing
1079 | | on the stack | addresses
1080 PARENT arg pointer -> | | /
1081 -------------------------- ---- -------------------
1082 CHILD |ret | return address
1084 | | \
1085 | | call saved
1086 | | registers
1087 | | /
1089 | | \
1090 | | local
1091 | | variables
1092 frame pointer -> | | /
1094 | | \
1095 | | outgoing | Decreasing
1096 | | arguments | addresses
1097 current stack pointer -> | | / |
1098 -------------------------- ---- ------------------ V
1099 | | */
1101 static unsigned int
1102 bit_count (unsigned int x)
1104 const unsigned int m1 = 0x55555555;
1105 const unsigned int m2 = 0x33333333;
1106 const unsigned int m4 = 0x0f0f0f0f;
1108 x -= (x >> 1) & m1;
1109 x = (x & m2) + ((x >> 2) & m2);
1110 x = (x + (x >> 4)) & m4;
1111 x += x >> 8;
1113 return (x + (x >> 16)) & 0x3f;
1116 #define MUST_SAVE_ACC_REGISTER \
1117 (TARGET_SAVE_ACC_REGISTER \
1118 && (is_interrupt_func (NULL_TREE) \
1119 || is_fast_interrupt_func (NULL_TREE)))
1121 /* Returns either the lowest numbered and highest numbered registers that
1122 occupy the call-saved area of the stack frame, if the registers are
1123 stored as a contiguous block, or else a bitmask of the individual
1124 registers if they are stored piecemeal.
1126 Also computes the size of the frame and the size of the outgoing
1127 arguments block (in bytes). */
1129 static void
1130 rx_get_stack_layout (unsigned int * lowest,
1131 unsigned int * highest,
1132 unsigned int * register_mask,
1133 unsigned int * frame_size,
1134 unsigned int * stack_size)
1136 unsigned int reg;
1137 unsigned int low;
1138 unsigned int high;
1139 unsigned int fixed_reg = 0;
1140 unsigned int save_mask;
1141 unsigned int pushed_mask;
1142 unsigned int unneeded_pushes;
1144 if (is_naked_func (NULL_TREE))
1146 /* Naked functions do not create their own stack frame.
1147 Instead the programmer must do that for us. */
1148 * lowest = 0;
1149 * highest = 0;
1150 * register_mask = 0;
1151 * frame_size = 0;
1152 * stack_size = 0;
1153 return;
1156 for (save_mask = high = low = 0, reg = 1; reg < CC_REGNUM; reg++)
1158 if ((df_regs_ever_live_p (reg)
1159 /* Always save all call clobbered registers inside non-leaf
1160 interrupt handlers, even if they are not live - they may
1161 be used in (non-interrupt aware) routines called from this one. */
1162 || (call_used_regs[reg]
1163 && is_interrupt_func (NULL_TREE)
1164 && ! current_function_is_leaf))
1165 && (! call_used_regs[reg]
1166 /* Even call clobbered registered must
1167 be pushed inside interrupt handlers. */
1168 || is_interrupt_func (NULL_TREE)
1169 /* Likewise for fast interrupt handlers, except registers r10 -
1170 r13. These are normally call-saved, but may have been set
1171 to call-used by rx_conditional_register_usage. If so then
1172 they can be used in the fast interrupt handler without
1173 saving them on the stack. */
1174 || (is_fast_interrupt_func (NULL_TREE)
1175 && ! IN_RANGE (reg, 10, 13))))
1177 if (low == 0)
1178 low = reg;
1179 high = reg;
1181 save_mask |= 1 << reg;
1184 /* Remember if we see a fixed register
1185 after having found the low register. */
1186 if (low != 0 && fixed_reg == 0 && fixed_regs [reg])
1187 fixed_reg = reg;
1190 /* If we have to save the accumulator register, make sure
1191 that at least two registers are pushed into the frame. */
1192 if (MUST_SAVE_ACC_REGISTER
1193 && bit_count (save_mask) < 2)
1195 save_mask |= (1 << 13) | (1 << 14);
1196 if (low == 0)
1197 low = 13;
1198 if (high == 0 || low == high)
1199 high = low + 1;
1202 /* Decide if it would be faster fill in the call-saved area of the stack
1203 frame using multiple PUSH instructions instead of a single PUSHM
1204 instruction.
1206 SAVE_MASK is a bitmask of the registers that must be stored in the
1207 call-save area. PUSHED_MASK is a bitmask of the registers that would
1208 be pushed into the area if we used a PUSHM instruction. UNNEEDED_PUSHES
1209 is a bitmask of those registers in pushed_mask that are not in
1210 save_mask.
1212 We use a simple heuristic that says that it is better to use
1213 multiple PUSH instructions if the number of unnecessary pushes is
1214 greater than the number of necessary pushes.
1216 We also use multiple PUSH instructions if there are any fixed registers
1217 between LOW and HIGH. The only way that this can happen is if the user
1218 has specified --fixed-<reg-name> on the command line and in such
1219 circumstances we do not want to touch the fixed registers at all.
1221 FIXME: Is it worth improving this heuristic ? */
1222 pushed_mask = (-1 << low) & ~(-1 << (high + 1));
1223 unneeded_pushes = (pushed_mask & (~ save_mask)) & pushed_mask;
1225 if ((fixed_reg && fixed_reg <= high)
1226 || (optimize_function_for_speed_p (cfun)
1227 && bit_count (save_mask) < bit_count (unneeded_pushes)))
1229 /* Use multiple pushes. */
1230 * lowest = 0;
1231 * highest = 0;
1232 * register_mask = save_mask;
1234 else
1236 /* Use one push multiple instruction. */
1237 * lowest = low;
1238 * highest = high;
1239 * register_mask = 0;
1242 * frame_size = rx_round_up
1243 (get_frame_size (), STACK_BOUNDARY / BITS_PER_UNIT);
1245 if (crtl->args.size > 0)
1246 * frame_size += rx_round_up
1247 (crtl->args.size, STACK_BOUNDARY / BITS_PER_UNIT);
1249 * stack_size = rx_round_up
1250 (crtl->outgoing_args_size, STACK_BOUNDARY / BITS_PER_UNIT);
1253 /* Generate a PUSHM instruction that matches the given operands. */
1255 void
1256 rx_emit_stack_pushm (rtx * operands)
1258 HOST_WIDE_INT last_reg;
1259 rtx first_push;
1261 gcc_assert (CONST_INT_P (operands[0]));
1262 last_reg = (INTVAL (operands[0]) / UNITS_PER_WORD) - 1;
1264 gcc_assert (GET_CODE (operands[1]) == PARALLEL);
1265 first_push = XVECEXP (operands[1], 0, 1);
1266 gcc_assert (SET_P (first_push));
1267 first_push = SET_SRC (first_push);
1268 gcc_assert (REG_P (first_push));
1270 asm_fprintf (asm_out_file, "\tpushm\t%s-%s\n",
1271 reg_names [REGNO (first_push) - last_reg],
1272 reg_names [REGNO (first_push)]);
1275 /* Generate a PARALLEL that will pass the rx_store_multiple_vector predicate. */
1277 static rtx
1278 gen_rx_store_vector (unsigned int low, unsigned int high)
1280 unsigned int i;
1281 unsigned int count = (high - low) + 2;
1282 rtx vector;
1284 vector = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
1286 XVECEXP (vector, 0, 0) =
1287 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
1288 gen_rtx_MINUS (SImode, stack_pointer_rtx,
1289 GEN_INT ((count - 1) * UNITS_PER_WORD)));
1291 for (i = 0; i < count - 1; i++)
1292 XVECEXP (vector, 0, i + 1) =
1293 gen_rtx_SET (VOIDmode,
1294 gen_rtx_MEM (SImode,
1295 gen_rtx_MINUS (SImode, stack_pointer_rtx,
1296 GEN_INT ((i + 1) * UNITS_PER_WORD))),
1297 gen_rtx_REG (SImode, high - i));
1298 return vector;
1301 /* Mark INSN as being frame related. If it is a PARALLEL
1302 then mark each element as being frame related as well. */
1304 static void
1305 mark_frame_related (rtx insn)
1307 RTX_FRAME_RELATED_P (insn) = 1;
1308 insn = PATTERN (insn);
1310 if (GET_CODE (insn) == PARALLEL)
1312 unsigned int i;
1314 for (i = 0; i < (unsigned) XVECLEN (insn, 0); i++)
1315 RTX_FRAME_RELATED_P (XVECEXP (insn, 0, i)) = 1;
1319 static bool
1320 ok_for_max_constant (HOST_WIDE_INT val)
1322 if (rx_max_constant_size == 0 || rx_max_constant_size == 4)
1323 /* If there is no constraint on the size of constants
1324 used as operands, then any value is legitimate. */
1325 return true;
1327 /* rx_max_constant_size specifies the maximum number
1328 of bytes that can be used to hold a signed value. */
1329 return IN_RANGE (val, (-1 << (rx_max_constant_size * 8)),
1330 ( 1 << (rx_max_constant_size * 8)));
1333 /* Generate an ADD of SRC plus VAL into DEST.
1334 Handles the case where VAL is too big for max_constant_value.
1335 Sets FRAME_RELATED_P on the insn if IS_FRAME_RELATED is true. */
1337 static void
1338 gen_safe_add (rtx dest, rtx src, rtx val, bool is_frame_related)
1340 rtx insn;
1342 if (val == NULL_RTX || INTVAL (val) == 0)
1344 gcc_assert (dest != src);
1346 insn = emit_move_insn (dest, src);
1348 else if (ok_for_max_constant (INTVAL (val)))
1349 insn = emit_insn (gen_addsi3 (dest, src, val));
1350 else
1352 /* Wrap VAL in an UNSPEC so that rx_legitimate_constant_p
1353 will not reject it. */
1354 val = gen_rtx_CONST (SImode, gen_rtx_UNSPEC (SImode, gen_rtvec (1, val), UNSPEC_CONST));
1355 insn = emit_insn (gen_addsi3 (dest, src, val));
1357 if (is_frame_related)
1358 /* We have to provide our own frame related note here
1359 as the dwarf2out code cannot be expected to grok
1360 our unspec. */
1361 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
1362 gen_rtx_SET (SImode, dest,
1363 gen_rtx_PLUS (SImode, src, val)));
1364 return;
1367 if (is_frame_related)
1368 RTX_FRAME_RELATED_P (insn) = 1;
1369 return;
1372 void
1373 rx_expand_prologue (void)
1375 unsigned int stack_size;
1376 unsigned int frame_size;
1377 unsigned int mask;
1378 unsigned int low;
1379 unsigned int high;
1380 unsigned int reg;
1381 rtx insn;
1383 /* Naked functions use their own, programmer provided prologues. */
1384 if (is_naked_func (NULL_TREE))
1385 return;
1387 rx_get_stack_layout (& low, & high, & mask, & frame_size, & stack_size);
1389 /* If we use any of the callee-saved registers, save them now. */
1390 if (mask)
1392 /* Push registers in reverse order. */
1393 for (reg = CC_REGNUM; reg --;)
1394 if (mask & (1 << reg))
1396 insn = emit_insn (gen_stack_push (gen_rtx_REG (SImode, reg)));
1397 mark_frame_related (insn);
1400 else if (low)
1402 if (high == low)
1403 insn = emit_insn (gen_stack_push (gen_rtx_REG (SImode, low)));
1404 else
1405 insn = emit_insn (gen_stack_pushm (GEN_INT (((high - low) + 1)
1406 * UNITS_PER_WORD),
1407 gen_rx_store_vector (low, high)));
1408 mark_frame_related (insn);
1411 if (MUST_SAVE_ACC_REGISTER)
1413 unsigned int acc_high, acc_low;
1415 /* Interrupt handlers have to preserve the accumulator
1416 register if so requested by the user. Use the first
1417 two pushed registers as intermediaries. */
1418 if (mask)
1420 acc_low = acc_high = 0;
1422 for (reg = 1; reg < CC_REGNUM; reg ++)
1423 if (mask & (1 << reg))
1425 if (acc_low == 0)
1426 acc_low = reg;
1427 else
1429 acc_high = reg;
1430 break;
1434 /* We have assumed that there are at least two registers pushed... */
1435 gcc_assert (acc_high != 0);
1437 /* Note - the bottom 16 bits of the accumulator are inaccessible.
1438 We just assume that they are zero. */
1439 emit_insn (gen_mvfacmi (gen_rtx_REG (SImode, acc_low)));
1440 emit_insn (gen_mvfachi (gen_rtx_REG (SImode, acc_high)));
1441 emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_low)));
1442 emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_high)));
1444 else
1446 acc_low = low;
1447 acc_high = low + 1;
1449 /* We have assumed that there are at least two registers pushed... */
1450 gcc_assert (acc_high <= high);
1452 emit_insn (gen_mvfacmi (gen_rtx_REG (SImode, acc_low)));
1453 emit_insn (gen_mvfachi (gen_rtx_REG (SImode, acc_high)));
1454 emit_insn (gen_stack_pushm (GEN_INT (2 * UNITS_PER_WORD),
1455 gen_rx_store_vector (acc_low, acc_high)));
1459 /* If needed, set up the frame pointer. */
1460 if (frame_pointer_needed)
1461 gen_safe_add (frame_pointer_rtx, stack_pointer_rtx,
1462 GEN_INT (- (HOST_WIDE_INT) frame_size), true);
1464 /* Allocate space for the outgoing args.
1465 If the stack frame has not already been set up then handle this as well. */
1466 if (stack_size)
1468 if (frame_size)
1470 if (frame_pointer_needed)
1471 gen_safe_add (stack_pointer_rtx, frame_pointer_rtx,
1472 GEN_INT (- (HOST_WIDE_INT) stack_size), true);
1473 else
1474 gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
1475 GEN_INT (- (HOST_WIDE_INT) (frame_size + stack_size)),
1476 true);
1478 else
1479 gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
1480 GEN_INT (- (HOST_WIDE_INT) stack_size), true);
1482 else if (frame_size)
1484 if (! frame_pointer_needed)
1485 gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
1486 GEN_INT (- (HOST_WIDE_INT) frame_size), true);
1487 else
1488 gen_safe_add (stack_pointer_rtx, frame_pointer_rtx, NULL_RTX,
1489 true);
1493 static void
1494 rx_output_function_prologue (FILE * file,
1495 HOST_WIDE_INT frame_size ATTRIBUTE_UNUSED)
1497 if (is_fast_interrupt_func (NULL_TREE))
1498 asm_fprintf (file, "\t; Note: Fast Interrupt Handler\n");
1500 if (is_interrupt_func (NULL_TREE))
1501 asm_fprintf (file, "\t; Note: Interrupt Handler\n");
1503 if (is_naked_func (NULL_TREE))
1504 asm_fprintf (file, "\t; Note: Naked Function\n");
1506 if (cfun->static_chain_decl != NULL)
1507 asm_fprintf (file, "\t; Note: Nested function declared "
1508 "inside another function.\n");
1510 if (crtl->calls_eh_return)
1511 asm_fprintf (file, "\t; Note: Calls __builtin_eh_return.\n");
1514 /* Generate a POPM or RTSD instruction that matches the given operands. */
1516 void
1517 rx_emit_stack_popm (rtx * operands, bool is_popm)
1519 HOST_WIDE_INT stack_adjust;
1520 HOST_WIDE_INT last_reg;
1521 rtx first_push;
1523 gcc_assert (CONST_INT_P (operands[0]));
1524 stack_adjust = INTVAL (operands[0]);
1526 gcc_assert (GET_CODE (operands[1]) == PARALLEL);
1527 last_reg = XVECLEN (operands[1], 0) - (is_popm ? 2 : 3);
1529 first_push = XVECEXP (operands[1], 0, 1);
1530 gcc_assert (SET_P (first_push));
1531 first_push = SET_DEST (first_push);
1532 gcc_assert (REG_P (first_push));
1534 if (is_popm)
1535 asm_fprintf (asm_out_file, "\tpopm\t%s-%s\n",
1536 reg_names [REGNO (first_push)],
1537 reg_names [REGNO (first_push) + last_reg]);
1538 else
1539 asm_fprintf (asm_out_file, "\trtsd\t#%d, %s-%s\n",
1540 (int) stack_adjust,
1541 reg_names [REGNO (first_push)],
1542 reg_names [REGNO (first_push) + last_reg]);
1545 /* Generate a PARALLEL which will satisfy the rx_rtsd_vector predicate. */
1547 static rtx
1548 gen_rx_rtsd_vector (unsigned int adjust, unsigned int low, unsigned int high)
1550 unsigned int i;
1551 unsigned int bias = 3;
1552 unsigned int count = (high - low) + bias;
1553 rtx vector;
1555 vector = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
1557 XVECEXP (vector, 0, 0) =
1558 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
1559 plus_constant (stack_pointer_rtx, adjust));
1561 for (i = 0; i < count - 2; i++)
1562 XVECEXP (vector, 0, i + 1) =
1563 gen_rtx_SET (VOIDmode,
1564 gen_rtx_REG (SImode, low + i),
1565 gen_rtx_MEM (SImode,
1566 i == 0 ? stack_pointer_rtx
1567 : plus_constant (stack_pointer_rtx,
1568 i * UNITS_PER_WORD)));
1570 XVECEXP (vector, 0, count - 1) = ret_rtx;
1572 return vector;
1575 /* Generate a PARALLEL which will satisfy the rx_load_multiple_vector predicate. */
1577 static rtx
1578 gen_rx_popm_vector (unsigned int low, unsigned int high)
1580 unsigned int i;
1581 unsigned int count = (high - low) + 2;
1582 rtx vector;
1584 vector = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
1586 XVECEXP (vector, 0, 0) =
1587 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
1588 plus_constant (stack_pointer_rtx,
1589 (count - 1) * UNITS_PER_WORD));
1591 for (i = 0; i < count - 1; i++)
1592 XVECEXP (vector, 0, i + 1) =
1593 gen_rtx_SET (VOIDmode,
1594 gen_rtx_REG (SImode, low + i),
1595 gen_rtx_MEM (SImode,
1596 i == 0 ? stack_pointer_rtx
1597 : plus_constant (stack_pointer_rtx,
1598 i * UNITS_PER_WORD)));
1600 return vector;
1603 void
1604 rx_expand_epilogue (bool is_sibcall)
1606 unsigned int low;
1607 unsigned int high;
1608 unsigned int frame_size;
1609 unsigned int stack_size;
1610 unsigned int register_mask;
1611 unsigned int regs_size;
1612 unsigned int reg;
1613 unsigned HOST_WIDE_INT total_size;
1615 /* FIXME: We do not support indirect sibcalls at the moment becaause we
1616 cannot guarantee that the register holding the function address is a
1617 call-used register. If it is a call-saved register then the stack
1618 pop instructions generated in the epilogue will corrupt the address
1619 before it is used.
1621 Creating a new call-used-only register class works but then the
1622 reload pass gets stuck because it cannot always find a call-used
1623 register for spilling sibcalls.
1625 The other possible solution is for this pass to scan forward for the
1626 sibcall instruction (if it has been generated) and work out if it
1627 is an indirect sibcall using a call-saved register. If it is then
1628 the address can copied into a call-used register in this epilogue
1629 code and the sibcall instruction modified to use that register. */
1631 if (is_naked_func (NULL_TREE))
1633 gcc_assert (! is_sibcall);
1635 /* Naked functions use their own, programmer provided epilogues.
1636 But, in order to keep gcc happy we have to generate some kind of
1637 epilogue RTL. */
1638 emit_jump_insn (gen_naked_return ());
1639 return;
1642 rx_get_stack_layout (& low, & high, & register_mask,
1643 & frame_size, & stack_size);
1645 total_size = frame_size + stack_size;
1646 regs_size = ((high - low) + 1) * UNITS_PER_WORD;
1648 /* See if we are unable to use the special stack frame deconstruct and
1649 return instructions. In most cases we can use them, but the exceptions
1650 are:
1652 - Sibling calling functions deconstruct the frame but do not return to
1653 their caller. Instead they branch to their sibling and allow their
1654 return instruction to return to this function's parent.
1656 - Fast and normal interrupt handling functions have to use special
1657 return instructions.
1659 - Functions where we have pushed a fragmented set of registers into the
1660 call-save area must have the same set of registers popped. */
1661 if (is_sibcall
1662 || is_fast_interrupt_func (NULL_TREE)
1663 || is_interrupt_func (NULL_TREE)
1664 || register_mask)
1666 /* Cannot use the special instructions - deconstruct by hand. */
1667 if (total_size)
1668 gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
1669 GEN_INT (total_size), false);
1671 if (MUST_SAVE_ACC_REGISTER)
1673 unsigned int acc_low, acc_high;
1675 /* Reverse the saving of the accumulator register onto the stack.
1676 Note we must adjust the saved "low" accumulator value as it
1677 is really the middle 32-bits of the accumulator. */
1678 if (register_mask)
1680 acc_low = acc_high = 0;
1682 for (reg = 1; reg < CC_REGNUM; reg ++)
1683 if (register_mask & (1 << reg))
1685 if (acc_low == 0)
1686 acc_low = reg;
1687 else
1689 acc_high = reg;
1690 break;
1693 emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_high)));
1694 emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_low)));
1696 else
1698 acc_low = low;
1699 acc_high = low + 1;
1700 emit_insn (gen_stack_popm (GEN_INT (2 * UNITS_PER_WORD),
1701 gen_rx_popm_vector (acc_low, acc_high)));
1704 emit_insn (gen_ashlsi3 (gen_rtx_REG (SImode, acc_low),
1705 gen_rtx_REG (SImode, acc_low),
1706 GEN_INT (16)));
1707 emit_insn (gen_mvtaclo (gen_rtx_REG (SImode, acc_low)));
1708 emit_insn (gen_mvtachi (gen_rtx_REG (SImode, acc_high)));
1711 if (register_mask)
1713 for (reg = 0; reg < CC_REGNUM; reg ++)
1714 if (register_mask & (1 << reg))
1715 emit_insn (gen_stack_pop (gen_rtx_REG (SImode, reg)));
1717 else if (low)
1719 if (high == low)
1720 emit_insn (gen_stack_pop (gen_rtx_REG (SImode, low)));
1721 else
1722 emit_insn (gen_stack_popm (GEN_INT (regs_size),
1723 gen_rx_popm_vector (low, high)));
1726 if (is_fast_interrupt_func (NULL_TREE))
1728 gcc_assert (! is_sibcall);
1729 emit_jump_insn (gen_fast_interrupt_return ());
1731 else if (is_interrupt_func (NULL_TREE))
1733 gcc_assert (! is_sibcall);
1734 emit_jump_insn (gen_exception_return ());
1736 else if (! is_sibcall)
1737 emit_jump_insn (gen_simple_return ());
1739 return;
1742 /* If we allocated space on the stack, free it now. */
1743 if (total_size)
1745 unsigned HOST_WIDE_INT rtsd_size;
1747 /* See if we can use the RTSD instruction. */
1748 rtsd_size = total_size + regs_size;
1749 if (rtsd_size < 1024 && (rtsd_size % 4) == 0)
1751 if (low)
1752 emit_jump_insn (gen_pop_and_return
1753 (GEN_INT (rtsd_size),
1754 gen_rx_rtsd_vector (rtsd_size, low, high)));
1755 else
1756 emit_jump_insn (gen_deallocate_and_return (GEN_INT (total_size)));
1758 return;
1761 gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
1762 GEN_INT (total_size), false);
1765 if (low)
1766 emit_jump_insn (gen_pop_and_return (GEN_INT (regs_size),
1767 gen_rx_rtsd_vector (regs_size,
1768 low, high)));
1769 else
1770 emit_jump_insn (gen_simple_return ());
1774 /* Compute the offset (in words) between FROM (arg pointer
1775 or frame pointer) and TO (frame pointer or stack pointer).
1776 See ASCII art comment at the start of rx_expand_prologue
1777 for more information. */
1780 rx_initial_elimination_offset (int from, int to)
1782 unsigned int low;
1783 unsigned int high;
1784 unsigned int frame_size;
1785 unsigned int stack_size;
1786 unsigned int mask;
1788 rx_get_stack_layout (& low, & high, & mask, & frame_size, & stack_size);
1790 if (from == ARG_POINTER_REGNUM)
1792 /* Extend the computed size of the stack frame to
1793 include the registers pushed in the prologue. */
1794 if (low)
1795 frame_size += ((high - low) + 1) * UNITS_PER_WORD;
1796 else
1797 frame_size += bit_count (mask) * UNITS_PER_WORD;
1799 /* Remember to include the return address. */
1800 frame_size += 1 * UNITS_PER_WORD;
1802 if (to == FRAME_POINTER_REGNUM)
1803 return frame_size;
1805 gcc_assert (to == STACK_POINTER_REGNUM);
1806 return frame_size + stack_size;
1809 gcc_assert (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM);
1810 return stack_size;
1813 /* Decide if a variable should go into one of the small data sections. */
1815 static bool
1816 rx_in_small_data (const_tree decl)
1818 int size;
1819 const_tree section;
1821 if (rx_small_data_limit == 0)
1822 return false;
1824 if (TREE_CODE (decl) != VAR_DECL)
1825 return false;
1827 /* We do not put read-only variables into a small data area because
1828 they would be placed with the other read-only sections, far away
1829 from the read-write data sections, and we only have one small
1830 data area pointer.
1831 Similarly commons are placed in the .bss section which might be
1832 far away (and out of alignment with respect to) the .data section. */
1833 if (TREE_READONLY (decl) || DECL_COMMON (decl))
1834 return false;
1836 section = DECL_SECTION_NAME (decl);
1837 if (section)
1839 const char * const name = TREE_STRING_POINTER (section);
1841 return (strcmp (name, "D_2") == 0) || (strcmp (name, "B_2") == 0);
1844 size = int_size_in_bytes (TREE_TYPE (decl));
1846 return (size > 0) && (size <= rx_small_data_limit);
1849 /* Return a section for X.
1850 The only special thing we do here is to honor small data. */
1852 static section *
1853 rx_select_rtx_section (enum machine_mode mode,
1854 rtx x,
1855 unsigned HOST_WIDE_INT align)
1857 if (rx_small_data_limit > 0
1858 && GET_MODE_SIZE (mode) <= rx_small_data_limit
1859 && align <= (unsigned HOST_WIDE_INT) rx_small_data_limit * BITS_PER_UNIT)
1860 return sdata_section;
1862 return default_elf_select_rtx_section (mode, x, align);
1865 static section *
1866 rx_select_section (tree decl,
1867 int reloc,
1868 unsigned HOST_WIDE_INT align)
1870 if (rx_small_data_limit > 0)
1872 switch (categorize_decl_for_section (decl, reloc))
1874 case SECCAT_SDATA: return sdata_section;
1875 case SECCAT_SBSS: return sbss_section;
1876 case SECCAT_SRODATA:
1877 /* Fall through. We do not put small, read only
1878 data into the C_2 section because we are not
1879 using the C_2 section. We do not use the C_2
1880 section because it is located with the other
1881 read-only data sections, far away from the read-write
1882 data sections and we only have one small data
1883 pointer (r13). */
1884 default:
1885 break;
1889 /* If we are supporting the Renesas assembler
1890 we cannot use mergeable sections. */
1891 if (TARGET_AS100_SYNTAX)
1892 switch (categorize_decl_for_section (decl, reloc))
1894 case SECCAT_RODATA_MERGE_CONST:
1895 case SECCAT_RODATA_MERGE_STR_INIT:
1896 case SECCAT_RODATA_MERGE_STR:
1897 return readonly_data_section;
1899 default:
1900 break;
1903 return default_elf_select_section (decl, reloc, align);
1906 enum rx_builtin
1908 RX_BUILTIN_BRK,
1909 RX_BUILTIN_CLRPSW,
1910 RX_BUILTIN_INT,
1911 RX_BUILTIN_MACHI,
1912 RX_BUILTIN_MACLO,
1913 RX_BUILTIN_MULHI,
1914 RX_BUILTIN_MULLO,
1915 RX_BUILTIN_MVFACHI,
1916 RX_BUILTIN_MVFACMI,
1917 RX_BUILTIN_MVFC,
1918 RX_BUILTIN_MVTACHI,
1919 RX_BUILTIN_MVTACLO,
1920 RX_BUILTIN_MVTC,
1921 RX_BUILTIN_MVTIPL,
1922 RX_BUILTIN_RACW,
1923 RX_BUILTIN_REVW,
1924 RX_BUILTIN_RMPA,
1925 RX_BUILTIN_ROUND,
1926 RX_BUILTIN_SETPSW,
1927 RX_BUILTIN_WAIT,
1928 RX_BUILTIN_max
1931 static void
1932 rx_init_builtins (void)
1934 #define ADD_RX_BUILTIN1(UC_NAME, LC_NAME, RET_TYPE, ARG_TYPE) \
1935 add_builtin_function ("__builtin_rx_" LC_NAME, \
1936 build_function_type_list (RET_TYPE##_type_node, \
1937 ARG_TYPE##_type_node, \
1938 NULL_TREE), \
1939 RX_BUILTIN_##UC_NAME, \
1940 BUILT_IN_MD, NULL, NULL_TREE)
1942 #define ADD_RX_BUILTIN2(UC_NAME, LC_NAME, RET_TYPE, ARG_TYPE1, ARG_TYPE2) \
1943 add_builtin_function ("__builtin_rx_" LC_NAME, \
1944 build_function_type_list (RET_TYPE##_type_node, \
1945 ARG_TYPE1##_type_node,\
1946 ARG_TYPE2##_type_node,\
1947 NULL_TREE), \
1948 RX_BUILTIN_##UC_NAME, \
1949 BUILT_IN_MD, NULL, NULL_TREE)
1951 #define ADD_RX_BUILTIN3(UC_NAME,LC_NAME,RET_TYPE,ARG_TYPE1,ARG_TYPE2,ARG_TYPE3) \
1952 add_builtin_function ("__builtin_rx_" LC_NAME, \
1953 build_function_type_list (RET_TYPE##_type_node, \
1954 ARG_TYPE1##_type_node,\
1955 ARG_TYPE2##_type_node,\
1956 ARG_TYPE3##_type_node,\
1957 NULL_TREE), \
1958 RX_BUILTIN_##UC_NAME, \
1959 BUILT_IN_MD, NULL, NULL_TREE)
1961 ADD_RX_BUILTIN1 (BRK, "brk", void, void);
1962 ADD_RX_BUILTIN1 (CLRPSW, "clrpsw", void, integer);
1963 ADD_RX_BUILTIN1 (SETPSW, "setpsw", void, integer);
1964 ADD_RX_BUILTIN1 (INT, "int", void, integer);
1965 ADD_RX_BUILTIN2 (MACHI, "machi", void, intSI, intSI);
1966 ADD_RX_BUILTIN2 (MACLO, "maclo", void, intSI, intSI);
1967 ADD_RX_BUILTIN2 (MULHI, "mulhi", void, intSI, intSI);
1968 ADD_RX_BUILTIN2 (MULLO, "mullo", void, intSI, intSI);
1969 ADD_RX_BUILTIN1 (MVFACHI, "mvfachi", intSI, void);
1970 ADD_RX_BUILTIN1 (MVFACMI, "mvfacmi", intSI, void);
1971 ADD_RX_BUILTIN1 (MVTACHI, "mvtachi", void, intSI);
1972 ADD_RX_BUILTIN1 (MVTACLO, "mvtaclo", void, intSI);
1973 ADD_RX_BUILTIN1 (RMPA, "rmpa", void, void);
1974 ADD_RX_BUILTIN1 (MVFC, "mvfc", intSI, integer);
1975 ADD_RX_BUILTIN2 (MVTC, "mvtc", void, integer, integer);
1976 ADD_RX_BUILTIN1 (MVTIPL, "mvtipl", void, integer);
1977 ADD_RX_BUILTIN1 (RACW, "racw", void, integer);
1978 ADD_RX_BUILTIN1 (ROUND, "round", intSI, float);
1979 ADD_RX_BUILTIN1 (REVW, "revw", intSI, intSI);
1980 ADD_RX_BUILTIN1 (WAIT, "wait", void, void);
1983 static rtx
1984 rx_expand_void_builtin_1_arg (rtx arg, rtx (* gen_func)(rtx), bool reg)
1986 if (reg && ! REG_P (arg))
1987 arg = force_reg (SImode, arg);
1989 emit_insn (gen_func (arg));
1991 return NULL_RTX;
1994 static rtx
1995 rx_expand_builtin_mvtc (tree exp)
1997 rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
1998 rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1));
2000 if (! CONST_INT_P (arg1))
2001 return NULL_RTX;
2003 if (! REG_P (arg2))
2004 arg2 = force_reg (SImode, arg2);
2006 emit_insn (gen_mvtc (arg1, arg2));
2008 return NULL_RTX;
2011 static rtx
2012 rx_expand_builtin_mvfc (tree t_arg, rtx target)
2014 rtx arg = expand_normal (t_arg);
2016 if (! CONST_INT_P (arg))
2017 return NULL_RTX;
2019 if (target == NULL_RTX)
2020 return NULL_RTX;
2022 if (! REG_P (target))
2023 target = force_reg (SImode, target);
2025 emit_insn (gen_mvfc (target, arg));
2027 return target;
2030 static rtx
2031 rx_expand_builtin_mvtipl (rtx arg)
2033 /* The RX610 does not support the MVTIPL instruction. */
2034 if (rx_cpu_type == RX610)
2035 return NULL_RTX;
2037 if (! CONST_INT_P (arg) || ! IN_RANGE (INTVAL (arg), 0, (1 << 4) - 1))
2038 return NULL_RTX;
2040 emit_insn (gen_mvtipl (arg));
2042 return NULL_RTX;
2045 static rtx
2046 rx_expand_builtin_mac (tree exp, rtx (* gen_func)(rtx, rtx))
2048 rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
2049 rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1));
2051 if (! REG_P (arg1))
2052 arg1 = force_reg (SImode, arg1);
2054 if (! REG_P (arg2))
2055 arg2 = force_reg (SImode, arg2);
2057 emit_insn (gen_func (arg1, arg2));
2059 return NULL_RTX;
2062 static rtx
2063 rx_expand_int_builtin_1_arg (rtx arg,
2064 rtx target,
2065 rtx (* gen_func)(rtx, rtx),
2066 bool mem_ok)
2068 if (! REG_P (arg))
2069 if (!mem_ok || ! MEM_P (arg))
2070 arg = force_reg (SImode, arg);
2072 if (target == NULL_RTX || ! REG_P (target))
2073 target = gen_reg_rtx (SImode);
2075 emit_insn (gen_func (target, arg));
2077 return target;
2080 static rtx
2081 rx_expand_int_builtin_0_arg (rtx target, rtx (* gen_func)(rtx))
2083 if (target == NULL_RTX || ! REG_P (target))
2084 target = gen_reg_rtx (SImode);
2086 emit_insn (gen_func (target));
2088 return target;
2091 static rtx
2092 rx_expand_builtin_round (rtx arg, rtx target)
2094 if ((! REG_P (arg) && ! MEM_P (arg))
2095 || GET_MODE (arg) != SFmode)
2096 arg = force_reg (SFmode, arg);
2098 if (target == NULL_RTX || ! REG_P (target))
2099 target = gen_reg_rtx (SImode);
2101 emit_insn (gen_lrintsf2 (target, arg));
2103 return target;
2106 static int
2107 valid_psw_flag (rtx op, const char *which)
2109 static int mvtc_inform_done = 0;
2111 if (GET_CODE (op) == CONST_INT)
2112 switch (INTVAL (op))
2114 case 0: case 'c': case 'C':
2115 case 1: case 'z': case 'Z':
2116 case 2: case 's': case 'S':
2117 case 3: case 'o': case 'O':
2118 case 8: case 'i': case 'I':
2119 case 9: case 'u': case 'U':
2120 return 1;
2123 error ("__builtin_rx_%s takes 'C', 'Z', 'S', 'O', 'I', or 'U'", which);
2124 if (!mvtc_inform_done)
2125 error ("use __builtin_rx_mvtc (0, ... ) to write arbitrary values to PSW");
2126 mvtc_inform_done = 1;
2128 return 0;
2131 static rtx
2132 rx_expand_builtin (tree exp,
2133 rtx target,
2134 rtx subtarget ATTRIBUTE_UNUSED,
2135 enum machine_mode mode ATTRIBUTE_UNUSED,
2136 int ignore ATTRIBUTE_UNUSED)
2138 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
2139 tree arg = call_expr_nargs (exp) >= 1 ? CALL_EXPR_ARG (exp, 0) : NULL_TREE;
2140 rtx op = arg ? expand_normal (arg) : NULL_RTX;
2141 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2143 switch (fcode)
2145 case RX_BUILTIN_BRK: emit_insn (gen_brk ()); return NULL_RTX;
2146 case RX_BUILTIN_CLRPSW:
2147 if (!valid_psw_flag (op, "clrpsw"))
2148 return NULL_RTX;
2149 return rx_expand_void_builtin_1_arg (op, gen_clrpsw, false);
2150 case RX_BUILTIN_SETPSW:
2151 if (!valid_psw_flag (op, "setpsw"))
2152 return NULL_RTX;
2153 return rx_expand_void_builtin_1_arg (op, gen_setpsw, false);
2154 case RX_BUILTIN_INT: return rx_expand_void_builtin_1_arg
2155 (op, gen_int, false);
2156 case RX_BUILTIN_MACHI: return rx_expand_builtin_mac (exp, gen_machi);
2157 case RX_BUILTIN_MACLO: return rx_expand_builtin_mac (exp, gen_maclo);
2158 case RX_BUILTIN_MULHI: return rx_expand_builtin_mac (exp, gen_mulhi);
2159 case RX_BUILTIN_MULLO: return rx_expand_builtin_mac (exp, gen_mullo);
2160 case RX_BUILTIN_MVFACHI: return rx_expand_int_builtin_0_arg
2161 (target, gen_mvfachi);
2162 case RX_BUILTIN_MVFACMI: return rx_expand_int_builtin_0_arg
2163 (target, gen_mvfacmi);
2164 case RX_BUILTIN_MVTACHI: return rx_expand_void_builtin_1_arg
2165 (op, gen_mvtachi, true);
2166 case RX_BUILTIN_MVTACLO: return rx_expand_void_builtin_1_arg
2167 (op, gen_mvtaclo, true);
2168 case RX_BUILTIN_RMPA: emit_insn (gen_rmpa ()); return NULL_RTX;
2169 case RX_BUILTIN_MVFC: return rx_expand_builtin_mvfc (arg, target);
2170 case RX_BUILTIN_MVTC: return rx_expand_builtin_mvtc (exp);
2171 case RX_BUILTIN_MVTIPL: return rx_expand_builtin_mvtipl (op);
2172 case RX_BUILTIN_RACW: return rx_expand_void_builtin_1_arg
2173 (op, gen_racw, false);
2174 case RX_BUILTIN_ROUND: return rx_expand_builtin_round (op, target);
2175 case RX_BUILTIN_REVW: return rx_expand_int_builtin_1_arg
2176 (op, target, gen_revw, false);
2177 case RX_BUILTIN_WAIT: emit_insn (gen_wait ()); return NULL_RTX;
2179 default:
2180 internal_error ("bad builtin code");
2181 break;
2184 return NULL_RTX;
2187 /* Place an element into a constructor or destructor section.
2188 Like default_ctor_section_asm_out_constructor in varasm.c
2189 except that it uses .init_array (or .fini_array) and it
2190 handles constructor priorities. */
2192 static void
2193 rx_elf_asm_cdtor (rtx symbol, int priority, bool is_ctor)
2195 section * s;
2197 if (priority != DEFAULT_INIT_PRIORITY)
2199 char buf[18];
2201 sprintf (buf, "%s.%.5u",
2202 is_ctor ? ".init_array" : ".fini_array",
2203 priority);
2204 s = get_section (buf, SECTION_WRITE, NULL_TREE);
2206 else if (is_ctor)
2207 s = ctors_section;
2208 else
2209 s = dtors_section;
2211 switch_to_section (s);
2212 assemble_align (POINTER_SIZE);
2213 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
2216 static void
2217 rx_elf_asm_constructor (rtx symbol, int priority)
2219 rx_elf_asm_cdtor (symbol, priority, /* is_ctor= */true);
2222 static void
2223 rx_elf_asm_destructor (rtx symbol, int priority)
2225 rx_elf_asm_cdtor (symbol, priority, /* is_ctor= */false);
2228 /* Check "fast_interrupt", "interrupt" and "naked" attributes. */
2230 static tree
2231 rx_handle_func_attribute (tree * node,
2232 tree name,
2233 tree args,
2234 int flags ATTRIBUTE_UNUSED,
2235 bool * no_add_attrs)
2237 gcc_assert (DECL_P (* node));
2238 gcc_assert (args == NULL_TREE);
2240 if (TREE_CODE (* node) != FUNCTION_DECL)
2242 warning (OPT_Wattributes, "%qE attribute only applies to functions",
2243 name);
2244 * no_add_attrs = true;
2247 /* FIXME: We ought to check for conflicting attributes. */
2249 /* FIXME: We ought to check that the interrupt and exception
2250 handler attributes have been applied to void functions. */
2251 return NULL_TREE;
2254 /* Table of RX specific attributes. */
2255 const struct attribute_spec rx_attribute_table[] =
2257 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
2258 affects_type_identity. */
2259 { "fast_interrupt", 0, 0, true, false, false, rx_handle_func_attribute,
2260 false },
2261 { "interrupt", 0, 0, true, false, false, rx_handle_func_attribute,
2262 false },
2263 { "naked", 0, 0, true, false, false, rx_handle_func_attribute,
2264 false },
2265 { NULL, 0, 0, false, false, false, NULL, false }
2268 /* Extra processing for target specific command line options. */
2270 static bool
2271 rx_handle_option (struct gcc_options *opts,
2272 struct gcc_options *opts_set ATTRIBUTE_UNUSED,
2273 const struct cl_decoded_option *decoded,
2274 location_t loc)
2276 size_t code = decoded->opt_index;
2277 int value = decoded->value;
2279 switch (code)
2281 case OPT_mint_register_:
2282 /* Make sure that the -mint-register option is in range. Other
2283 handling in rx_option_override. */
2284 return value >= 0 && value <= 4;
2285 break;
2287 case OPT_mmax_constant_size_:
2288 /* Make sure that the -mmax-constant_size option is in range. */
2289 return value >= 0 && value <= 4;
2291 case OPT_mcpu_:
2292 if ((enum rx_cpu_types) value == RX200)
2293 opts->x_target_flags |= MASK_NO_USE_FPU;
2294 break;
2296 case OPT_fpu:
2297 if (opts->x_rx_cpu_type == RX200)
2298 error_at (loc, "the RX200 cpu does not have FPU hardware");
2299 break;
2301 default:
2302 break;
2305 return true;
2308 /* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE. */
2310 static void
2311 rx_override_options_after_change (void)
2313 static bool first_time = TRUE;
2315 if (first_time)
2317 /* If this is the first time through and the user has not disabled
2318 the use of RX FPU hardware then enable -ffinite-math-only,
2319 since the FPU instructions do not support NaNs and infinities. */
2320 if (TARGET_USE_FPU)
2321 flag_finite_math_only = 1;
2323 first_time = FALSE;
2325 else
2327 /* Alert the user if they are changing the optimization options
2328 to use IEEE compliant floating point arithmetic with RX FPU insns. */
2329 if (TARGET_USE_FPU
2330 && !flag_finite_math_only)
2331 warning (0, "RX FPU instructions do not support NaNs and infinities");
2335 static void
2336 rx_option_override (void)
2338 unsigned int i;
2339 cl_deferred_option *opt;
2340 VEC(cl_deferred_option,heap) *vec
2341 = (VEC(cl_deferred_option,heap) *) rx_deferred_options;
2343 FOR_EACH_VEC_ELT (cl_deferred_option, vec, i, opt)
2345 switch (opt->opt_index)
2347 case OPT_mint_register_:
2348 switch (opt->value)
2350 case 4:
2351 fixed_regs[10] = call_used_regs [10] = 1;
2352 /* Fall through. */
2353 case 3:
2354 fixed_regs[11] = call_used_regs [11] = 1;
2355 /* Fall through. */
2356 case 2:
2357 fixed_regs[12] = call_used_regs [12] = 1;
2358 /* Fall through. */
2359 case 1:
2360 fixed_regs[13] = call_used_regs [13] = 1;
2361 /* Fall through. */
2362 case 0:
2363 break;
2364 default:
2365 /* Error message already given because rx_handle_option
2366 returned false. */
2367 break;
2369 break;
2371 default:
2372 gcc_unreachable ();
2376 /* This target defaults to strict volatile bitfields. */
2377 if (flag_strict_volatile_bitfields < 0)
2378 flag_strict_volatile_bitfields = 1;
2380 rx_override_options_after_change ();
2382 if (align_jumps == 0 && ! optimize_size)
2383 align_jumps = 3;
2384 if (align_loops == 0 && ! optimize_size)
2385 align_loops = 3;
2386 if (align_labels == 0 && ! optimize_size)
2387 align_labels = 3;
2390 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */
2391 static const struct default_options rx_option_optimization_table[] =
2393 { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
2394 { OPT_LEVELS_NONE, 0, NULL, 0 }
2398 static bool
2399 rx_allocate_stack_slots_for_args (void)
2401 /* Naked functions should not allocate stack slots for arguments. */
2402 return ! is_naked_func (NULL_TREE);
2405 static bool
2406 rx_func_attr_inlinable (const_tree decl)
2408 return ! is_fast_interrupt_func (decl)
2409 && ! is_interrupt_func (decl)
2410 && ! is_naked_func (decl);
2413 /* Return nonzero if it is ok to make a tail-call to DECL,
2414 a function_decl or NULL if this is an indirect call, using EXP */
2416 static bool
2417 rx_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
2419 /* Do not allow indirect tailcalls. The
2420 sibcall patterns do not support them. */
2421 if (decl == NULL)
2422 return false;
2424 /* Never tailcall from inside interrupt handlers or naked functions. */
2425 if (is_fast_interrupt_func (NULL_TREE)
2426 || is_interrupt_func (NULL_TREE)
2427 || is_naked_func (NULL_TREE))
2428 return false;
2430 return true;
2433 static void
2434 rx_file_start (void)
2436 if (! TARGET_AS100_SYNTAX)
2437 default_file_start ();
2440 static bool
2441 rx_is_ms_bitfield_layout (const_tree record_type ATTRIBUTE_UNUSED)
2443 /* The packed attribute overrides the MS behaviour. */
2444 return ! TYPE_PACKED (record_type);
2447 /* Returns true if X a legitimate constant for an immediate
2448 operand on the RX. X is already known to satisfy CONSTANT_P. */
2450 bool
2451 rx_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
2453 switch (GET_CODE (x))
2455 case CONST:
2456 x = XEXP (x, 0);
2458 if (GET_CODE (x) == PLUS)
2460 if (! CONST_INT_P (XEXP (x, 1)))
2461 return false;
2463 /* GCC would not pass us CONST_INT + CONST_INT so we
2464 know that we have {SYMBOL|LABEL} + CONST_INT. */
2465 x = XEXP (x, 0);
2466 gcc_assert (! CONST_INT_P (x));
2469 switch (GET_CODE (x))
2471 case LABEL_REF:
2472 case SYMBOL_REF:
2473 return true;
2475 case UNSPEC:
2476 return XINT (x, 1) == UNSPEC_CONST;
2478 default:
2479 /* FIXME: Can this ever happen ? */
2480 gcc_unreachable ();
2482 break;
2484 case LABEL_REF:
2485 case SYMBOL_REF:
2486 return true;
2487 case CONST_DOUBLE:
2488 return (rx_max_constant_size == 0 || rx_max_constant_size == 4);
2489 case CONST_VECTOR:
2490 return false;
2491 default:
2492 gcc_assert (CONST_INT_P (x));
2493 break;
2496 return ok_for_max_constant (INTVAL (x));
2499 static int
2500 rx_address_cost (rtx addr, bool speed)
2502 rtx a, b;
2504 if (GET_CODE (addr) != PLUS)
2505 return COSTS_N_INSNS (1);
2507 a = XEXP (addr, 0);
2508 b = XEXP (addr, 1);
2510 if (REG_P (a) && REG_P (b))
2511 /* Try to discourage REG+REG addressing as it keeps two registers live. */
2512 return COSTS_N_INSNS (4);
2514 if (speed)
2515 /* [REG+OFF] is just as fast as [REG]. */
2516 return COSTS_N_INSNS (1);
2518 if (CONST_INT_P (b)
2519 && ((INTVAL (b) > 128) || INTVAL (b) < -127))
2520 /* Try to discourage REG + <large OFF> when optimizing for size. */
2521 return COSTS_N_INSNS (2);
2523 return COSTS_N_INSNS (1);
2526 static bool
2527 rx_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
2529 /* We can always eliminate to the frame pointer.
2530 We can eliminate to the stack pointer unless a frame
2531 pointer is needed. */
2533 return to == FRAME_POINTER_REGNUM
2534 || ( to == STACK_POINTER_REGNUM && ! frame_pointer_needed);
2538 static void
2539 rx_trampoline_template (FILE * file)
2541 /* Output assembler code for a block containing the constant
2542 part of a trampoline, leaving space for the variable parts.
2544 On the RX, (where r8 is the static chain regnum) the trampoline
2545 looks like:
2547 mov #<static chain value>, r8
2548 mov #<function's address>, r9
2549 jmp r9
2551 In big-endian-data-mode however instructions are read into the CPU
2552 4 bytes at a time. These bytes are then swapped around before being
2553 passed to the decoder. So...we must partition our trampoline into
2554 4 byte packets and swap these packets around so that the instruction
2555 reader will reverse the process. But, in order to avoid splitting
2556 the 32-bit constants across these packet boundaries, (making inserting
2557 them into the constructed trampoline very difficult) we have to pad the
2558 instruction sequence with NOP insns. ie:
2562 mov.l #<...>, r8
2565 mov.l #<...>, r9
2566 jmp r9
2568 nop */
2570 if (! TARGET_BIG_ENDIAN_DATA)
2572 asm_fprintf (file, "\tmov.L\t#0deadbeefH, r%d\n", STATIC_CHAIN_REGNUM);
2573 asm_fprintf (file, "\tmov.L\t#0deadbeefH, r%d\n", TRAMPOLINE_TEMP_REGNUM);
2574 asm_fprintf (file, "\tjmp\tr%d\n", TRAMPOLINE_TEMP_REGNUM);
2576 else
2578 char r8 = '0' + STATIC_CHAIN_REGNUM;
2579 char r9 = '0' + TRAMPOLINE_TEMP_REGNUM;
2581 if (TARGET_AS100_SYNTAX)
2583 asm_fprintf (file, "\t.BYTE 0%c2H, 0fbH, 003H, 003H\n", r8);
2584 asm_fprintf (file, "\t.BYTE 0deH, 0adH, 0beH, 0efH\n");
2585 asm_fprintf (file, "\t.BYTE 0%c2H, 0fbH, 003H, 003H\n", r9);
2586 asm_fprintf (file, "\t.BYTE 0deH, 0adH, 0beH, 0efH\n");
2587 asm_fprintf (file, "\t.BYTE 003H, 003H, 00%cH, 07fH\n", r9);
2589 else
2591 asm_fprintf (file, "\t.byte 0x%c2, 0xfb, 0x03, 0x03\n", r8);
2592 asm_fprintf (file, "\t.byte 0xde, 0xad, 0xbe, 0xef\n");
2593 asm_fprintf (file, "\t.byte 0x%c2, 0xfb, 0x03, 0x03\n", r9);
2594 asm_fprintf (file, "\t.byte 0xde, 0xad, 0xbe, 0xef\n");
2595 asm_fprintf (file, "\t.byte 0x03, 0x03, 0x0%c, 0x7f\n", r9);
2600 static void
2601 rx_trampoline_init (rtx tramp, tree fndecl, rtx chain)
2603 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
2605 emit_block_move (tramp, assemble_trampoline_template (),
2606 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
2608 if (TARGET_BIG_ENDIAN_DATA)
2610 emit_move_insn (adjust_address (tramp, SImode, 4), chain);
2611 emit_move_insn (adjust_address (tramp, SImode, 12), fnaddr);
2613 else
2615 emit_move_insn (adjust_address (tramp, SImode, 2), chain);
2616 emit_move_insn (adjust_address (tramp, SImode, 6 + 2), fnaddr);
2620 static int
2621 rx_memory_move_cost (enum machine_mode mode, reg_class_t regclass, bool in)
2623 return (in ? 2 : 0) + memory_move_secondary_cost (mode, regclass, in);
2626 /* Convert a CC_MODE to the set of flags that it represents. */
2628 static unsigned int
2629 flags_from_mode (enum machine_mode mode)
2631 switch (mode)
2633 case CC_ZSmode:
2634 return CC_FLAG_S | CC_FLAG_Z;
2635 case CC_ZSOmode:
2636 return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_O;
2637 case CC_ZSCmode:
2638 return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_C;
2639 case CCmode:
2640 return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_O | CC_FLAG_C;
2641 case CC_Fmode:
2642 return CC_FLAG_FP;
2643 default:
2644 gcc_unreachable ();
2648 /* Convert a set of flags to a CC_MODE that can implement it. */
2650 static enum machine_mode
2651 mode_from_flags (unsigned int f)
2653 if (f & CC_FLAG_FP)
2654 return CC_Fmode;
2655 if (f & CC_FLAG_O)
2657 if (f & CC_FLAG_C)
2658 return CCmode;
2659 else
2660 return CC_ZSOmode;
2662 else if (f & CC_FLAG_C)
2663 return CC_ZSCmode;
2664 else
2665 return CC_ZSmode;
2668 /* Convert an RTX_CODE to the set of flags needed to implement it.
2669 This assumes an integer comparison. */
2671 static unsigned int
2672 flags_from_code (enum rtx_code code)
2674 switch (code)
2676 case LT:
2677 case GE:
2678 return CC_FLAG_S;
2679 case GT:
2680 case LE:
2681 return CC_FLAG_S | CC_FLAG_O | CC_FLAG_Z;
2682 case GEU:
2683 case LTU:
2684 return CC_FLAG_C;
2685 case GTU:
2686 case LEU:
2687 return CC_FLAG_C | CC_FLAG_Z;
2688 case EQ:
2689 case NE:
2690 return CC_FLAG_Z;
2691 default:
2692 gcc_unreachable ();
2696 /* Return a CC_MODE of which both M1 and M2 are subsets. */
2698 static enum machine_mode
2699 rx_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
2701 unsigned f;
2703 /* Early out for identical modes. */
2704 if (m1 == m2)
2705 return m1;
2707 /* There's no valid combination for FP vs non-FP. */
2708 f = flags_from_mode (m1) | flags_from_mode (m2);
2709 if (f & CC_FLAG_FP)
2710 return VOIDmode;
2712 /* Otherwise, see what mode can implement all the flags. */
2713 return mode_from_flags (f);
2716 /* Return the minimal CC mode needed to implement (CMP_CODE X Y). */
2718 enum machine_mode
2719 rx_select_cc_mode (enum rtx_code cmp_code, rtx x, rtx y)
2721 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
2722 return CC_Fmode;
2724 if (y != const0_rtx)
2725 return CCmode;
2727 return mode_from_flags (flags_from_code (cmp_code));
2730 /* Split the conditional branch. Emit (COMPARE C1 C2) into CC_REG with
2731 CC_MODE, and use that in branches based on that compare. */
2733 void
2734 rx_split_cbranch (enum machine_mode cc_mode, enum rtx_code cmp1,
2735 rtx c1, rtx c2, rtx label)
2737 rtx flags, x;
2739 flags = gen_rtx_REG (cc_mode, CC_REG);
2740 x = gen_rtx_COMPARE (cc_mode, c1, c2);
2741 x = gen_rtx_SET (VOIDmode, flags, x);
2742 emit_insn (x);
2744 x = gen_rtx_fmt_ee (cmp1, VOIDmode, flags, const0_rtx);
2745 x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label, pc_rtx);
2746 x = gen_rtx_SET (VOIDmode, pc_rtx, x);
2747 emit_jump_insn (x);
2750 /* A helper function for matching parallels that set the flags. */
2752 bool
2753 rx_match_ccmode (rtx insn, enum machine_mode cc_mode)
2755 rtx op1, flags;
2756 enum machine_mode flags_mode;
2758 gcc_checking_assert (XVECLEN (PATTERN (insn), 0) == 2);
2760 op1 = XVECEXP (PATTERN (insn), 0, 1);
2761 gcc_checking_assert (GET_CODE (SET_SRC (op1)) == COMPARE);
2763 flags = SET_DEST (op1);
2764 flags_mode = GET_MODE (flags);
2766 if (GET_MODE (SET_SRC (op1)) != flags_mode)
2767 return false;
2768 if (GET_MODE_CLASS (flags_mode) != MODE_CC)
2769 return false;
2771 /* Ensure that the mode of FLAGS is compatible with CC_MODE. */
2772 if (flags_from_mode (flags_mode) & ~flags_from_mode (cc_mode))
2773 return false;
2775 return true;
2779 rx_align_for_label (void)
2781 return optimize_size ? 1 : 3;
2784 static int
2785 rx_max_skip_for_label (rtx lab)
2787 int opsize;
2788 rtx op;
2790 if (lab == NULL_RTX)
2791 return 0;
2793 op = lab;
2796 op = next_nonnote_nondebug_insn (op);
2798 while (op && (LABEL_P (op)
2799 || (INSN_P (op) && GET_CODE (PATTERN (op)) == USE)));
2800 if (!op)
2801 return 0;
2803 opsize = get_attr_length (op);
2804 if (opsize >= 0 && opsize < 8)
2805 return opsize - 1;
2806 return 0;
2809 /* Compute the real length of the extending load-and-op instructions. */
2812 rx_adjust_insn_length (rtx insn, int current_length)
2814 rtx extend, mem, offset;
2815 bool zero;
2816 int factor;
2818 switch (INSN_CODE (insn))
2820 default:
2821 return current_length;
2823 case CODE_FOR_plussi3_zero_extendhi:
2824 case CODE_FOR_andsi3_zero_extendhi:
2825 case CODE_FOR_iorsi3_zero_extendhi:
2826 case CODE_FOR_xorsi3_zero_extendhi:
2827 case CODE_FOR_divsi3_zero_extendhi:
2828 case CODE_FOR_udivsi3_zero_extendhi:
2829 case CODE_FOR_minussi3_zero_extendhi:
2830 case CODE_FOR_smaxsi3_zero_extendhi:
2831 case CODE_FOR_sminsi3_zero_extendhi:
2832 case CODE_FOR_multsi3_zero_extendhi:
2833 case CODE_FOR_comparesi3_zero_extendqi:
2834 zero = true;
2835 factor = 2;
2836 break;
2838 case CODE_FOR_plussi3_sign_extendhi:
2839 case CODE_FOR_andsi3_sign_extendhi:
2840 case CODE_FOR_iorsi3_sign_extendhi:
2841 case CODE_FOR_xorsi3_sign_extendhi:
2842 case CODE_FOR_divsi3_sign_extendhi:
2843 case CODE_FOR_udivsi3_sign_extendhi:
2844 case CODE_FOR_minussi3_sign_extendhi:
2845 case CODE_FOR_smaxsi3_sign_extendhi:
2846 case CODE_FOR_sminsi3_sign_extendhi:
2847 case CODE_FOR_multsi3_sign_extendhi:
2848 case CODE_FOR_comparesi3_zero_extendhi:
2849 zero = false;
2850 factor = 2;
2851 break;
2853 case CODE_FOR_plussi3_zero_extendqi:
2854 case CODE_FOR_andsi3_zero_extendqi:
2855 case CODE_FOR_iorsi3_zero_extendqi:
2856 case CODE_FOR_xorsi3_zero_extendqi:
2857 case CODE_FOR_divsi3_zero_extendqi:
2858 case CODE_FOR_udivsi3_zero_extendqi:
2859 case CODE_FOR_minussi3_zero_extendqi:
2860 case CODE_FOR_smaxsi3_zero_extendqi:
2861 case CODE_FOR_sminsi3_zero_extendqi:
2862 case CODE_FOR_multsi3_zero_extendqi:
2863 case CODE_FOR_comparesi3_sign_extendqi:
2864 zero = true;
2865 factor = 1;
2866 break;
2868 case CODE_FOR_plussi3_sign_extendqi:
2869 case CODE_FOR_andsi3_sign_extendqi:
2870 case CODE_FOR_iorsi3_sign_extendqi:
2871 case CODE_FOR_xorsi3_sign_extendqi:
2872 case CODE_FOR_divsi3_sign_extendqi:
2873 case CODE_FOR_udivsi3_sign_extendqi:
2874 case CODE_FOR_minussi3_sign_extendqi:
2875 case CODE_FOR_smaxsi3_sign_extendqi:
2876 case CODE_FOR_sminsi3_sign_extendqi:
2877 case CODE_FOR_multsi3_sign_extendqi:
2878 case CODE_FOR_comparesi3_sign_extendhi:
2879 zero = false;
2880 factor = 1;
2881 break;
2884 /* We are expecting: (SET (REG) (<OP> (REG) (<EXTEND> (MEM)))). */
2885 extend = single_set (insn);
2886 gcc_assert (extend != NULL_RTX);
2888 extend = SET_SRC (extend);
2889 if (GET_CODE (XEXP (extend, 0)) == ZERO_EXTEND
2890 || GET_CODE (XEXP (extend, 0)) == SIGN_EXTEND)
2891 extend = XEXP (extend, 0);
2892 else
2893 extend = XEXP (extend, 1);
2895 gcc_assert ((zero && (GET_CODE (extend) == ZERO_EXTEND))
2896 || (! zero && (GET_CODE (extend) == SIGN_EXTEND)));
2898 mem = XEXP (extend, 0);
2899 gcc_checking_assert (MEM_P (mem));
2900 if (REG_P (XEXP (mem, 0)))
2901 return (zero && factor == 1) ? 2 : 3;
2903 /* We are expecting: (MEM (PLUS (REG) (CONST_INT))). */
2904 gcc_checking_assert (GET_CODE (XEXP (mem, 0)) == PLUS);
2905 gcc_checking_assert (REG_P (XEXP (XEXP (mem, 0), 0)));
2907 offset = XEXP (XEXP (mem, 0), 1);
2908 gcc_checking_assert (GET_CODE (offset) == CONST_INT);
2910 if (IN_RANGE (INTVAL (offset), 0, 255 * factor))
2911 return (zero && factor == 1) ? 3 : 4;
2913 return (zero && factor == 1) ? 4 : 5;
2916 #undef TARGET_ASM_JUMP_ALIGN_MAX_SKIP
2917 #define TARGET_ASM_JUMP_ALIGN_MAX_SKIP rx_max_skip_for_label
2918 #undef TARGET_ASM_LOOP_ALIGN_MAX_SKIP
2919 #define TARGET_ASM_LOOP_ALIGN_MAX_SKIP rx_max_skip_for_label
2920 #undef TARGET_LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP
2921 #define TARGET_LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP rx_max_skip_for_label
2922 #undef TARGET_ASM_LABEL_ALIGN_MAX_SKIP
2923 #define TARGET_ASM_LABEL_ALIGN_MAX_SKIP rx_max_skip_for_label
2925 #undef TARGET_FUNCTION_VALUE
2926 #define TARGET_FUNCTION_VALUE rx_function_value
2928 #undef TARGET_RETURN_IN_MSB
2929 #define TARGET_RETURN_IN_MSB rx_return_in_msb
2931 #undef TARGET_IN_SMALL_DATA_P
2932 #define TARGET_IN_SMALL_DATA_P rx_in_small_data
2934 #undef TARGET_RETURN_IN_MEMORY
2935 #define TARGET_RETURN_IN_MEMORY rx_return_in_memory
2937 #undef TARGET_HAVE_SRODATA_SECTION
2938 #define TARGET_HAVE_SRODATA_SECTION true
2940 #undef TARGET_ASM_SELECT_RTX_SECTION
2941 #define TARGET_ASM_SELECT_RTX_SECTION rx_select_rtx_section
2943 #undef TARGET_ASM_SELECT_SECTION
2944 #define TARGET_ASM_SELECT_SECTION rx_select_section
2946 #undef TARGET_INIT_BUILTINS
2947 #define TARGET_INIT_BUILTINS rx_init_builtins
2949 #undef TARGET_EXPAND_BUILTIN
2950 #define TARGET_EXPAND_BUILTIN rx_expand_builtin
2952 #undef TARGET_ASM_CONSTRUCTOR
2953 #define TARGET_ASM_CONSTRUCTOR rx_elf_asm_constructor
2955 #undef TARGET_ASM_DESTRUCTOR
2956 #define TARGET_ASM_DESTRUCTOR rx_elf_asm_destructor
2958 #undef TARGET_STRUCT_VALUE_RTX
2959 #define TARGET_STRUCT_VALUE_RTX rx_struct_value_rtx
2961 #undef TARGET_ATTRIBUTE_TABLE
2962 #define TARGET_ATTRIBUTE_TABLE rx_attribute_table
2964 #undef TARGET_ASM_FILE_START
2965 #define TARGET_ASM_FILE_START rx_file_start
2967 #undef TARGET_MS_BITFIELD_LAYOUT_P
2968 #define TARGET_MS_BITFIELD_LAYOUT_P rx_is_ms_bitfield_layout
2970 #undef TARGET_LEGITIMATE_ADDRESS_P
2971 #define TARGET_LEGITIMATE_ADDRESS_P rx_is_legitimate_address
2973 #undef TARGET_MODE_DEPENDENT_ADDRESS_P
2974 #define TARGET_MODE_DEPENDENT_ADDRESS_P rx_mode_dependent_address_p
2976 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
2977 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS rx_allocate_stack_slots_for_args
2979 #undef TARGET_ASM_FUNCTION_PROLOGUE
2980 #define TARGET_ASM_FUNCTION_PROLOGUE rx_output_function_prologue
2982 #undef TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P
2983 #define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P rx_func_attr_inlinable
2985 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
2986 #define TARGET_FUNCTION_OK_FOR_SIBCALL rx_function_ok_for_sibcall
2988 #undef TARGET_FUNCTION_ARG
2989 #define TARGET_FUNCTION_ARG rx_function_arg
2991 #undef TARGET_FUNCTION_ARG_ADVANCE
2992 #define TARGET_FUNCTION_ARG_ADVANCE rx_function_arg_advance
2994 #undef TARGET_FUNCTION_ARG_BOUNDARY
2995 #define TARGET_FUNCTION_ARG_BOUNDARY rx_function_arg_boundary
2997 #undef TARGET_SET_CURRENT_FUNCTION
2998 #define TARGET_SET_CURRENT_FUNCTION rx_set_current_function
3000 #undef TARGET_HANDLE_OPTION
3001 #define TARGET_HANDLE_OPTION rx_handle_option
3003 #undef TARGET_ASM_INTEGER
3004 #define TARGET_ASM_INTEGER rx_assemble_integer
3006 #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
3007 #define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_true
3009 #undef TARGET_MAX_ANCHOR_OFFSET
3010 #define TARGET_MAX_ANCHOR_OFFSET 32
3012 #undef TARGET_ADDRESS_COST
3013 #define TARGET_ADDRESS_COST rx_address_cost
3015 #undef TARGET_CAN_ELIMINATE
3016 #define TARGET_CAN_ELIMINATE rx_can_eliminate
3018 #undef TARGET_CONDITIONAL_REGISTER_USAGE
3019 #define TARGET_CONDITIONAL_REGISTER_USAGE rx_conditional_register_usage
3021 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
3022 #define TARGET_ASM_TRAMPOLINE_TEMPLATE rx_trampoline_template
3024 #undef TARGET_TRAMPOLINE_INIT
3025 #define TARGET_TRAMPOLINE_INIT rx_trampoline_init
3027 #undef TARGET_PRINT_OPERAND
3028 #define TARGET_PRINT_OPERAND rx_print_operand
3030 #undef TARGET_PRINT_OPERAND_ADDRESS
3031 #define TARGET_PRINT_OPERAND_ADDRESS rx_print_operand_address
3033 #undef TARGET_CC_MODES_COMPATIBLE
3034 #define TARGET_CC_MODES_COMPATIBLE rx_cc_modes_compatible
3036 #undef TARGET_MEMORY_MOVE_COST
3037 #define TARGET_MEMORY_MOVE_COST rx_memory_move_cost
3039 #undef TARGET_OPTION_OVERRIDE
3040 #define TARGET_OPTION_OVERRIDE rx_option_override
3042 #undef TARGET_OPTION_OPTIMIZATION_TABLE
3043 #define TARGET_OPTION_OPTIMIZATION_TABLE rx_option_optimization_table
3045 #undef TARGET_PROMOTE_FUNCTION_MODE
3046 #define TARGET_PROMOTE_FUNCTION_MODE rx_promote_function_mode
3048 #undef TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE
3049 #define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE rx_override_options_after_change
3051 #undef TARGET_EXCEPT_UNWIND_INFO
3052 #define TARGET_EXCEPT_UNWIND_INFO sjlj_except_unwind_info
3054 #undef TARGET_FLAGS_REGNUM
3055 #define TARGET_FLAGS_REGNUM CC_REG
3057 #undef TARGET_LEGITIMATE_CONSTANT_P
3058 #define TARGET_LEGITIMATE_CONSTANT_P rx_legitimate_constant_p
3060 struct gcc_target targetm = TARGET_INITIALIZER;
3062 /* #include "gt-rx.h" */