1 /* Subroutines used for code generation on the Argonaut ARC cpu.
2 Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4 Free Software Foundation, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to
20 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
23 /* ??? This is an old port, and is undoubtedly suffering from bit rot. */
27 #include "coretypes.h"
32 #include "hard-reg-set.h"
34 #include "insn-config.h"
35 #include "conditions.h"
37 #include "insn-attr.h"
45 #include "target-def.h"
47 /* Which cpu we're compiling for. */
50 /* Name of mangle string to add to symbols to separate code compiled for each
52 const char *arc_mangle_cpu
;
54 /* Save the operands last given to a compare for use when we
55 generate a scc or bcc insn. */
56 rtx arc_compare_op0
, arc_compare_op1
;
58 /* Name of text, data, and rodata sections used in varasm.c. */
59 const char *arc_text_section
;
60 const char *arc_data_section
;
61 const char *arc_rodata_section
;
63 /* Array of valid operand punctuation characters. */
64 char arc_punct_chars
[256];
66 /* Variables used by arc_final_prescan_insn to implement conditional
68 static int arc_ccfsm_state
;
69 static int arc_ccfsm_current_cc
;
70 static rtx arc_ccfsm_target_insn
;
71 static int arc_ccfsm_target_label
;
73 /* The maximum number of insns skipped which will be conditionalised if
75 #define MAX_INSNS_SKIPPED 3
77 /* A nop is needed between a 4 byte insn that sets the condition codes and
78 a branch that uses them (the same isn't true for an 8 byte insn that sets
79 the condition codes). Set by arc_final_prescan_insn. Used by
81 static int last_insn_set_cc_p
;
82 static int current_insn_set_cc_p
;
83 static bool arc_handle_option (size_t, const char *, int);
84 static void record_cc_ref (rtx
);
85 static void arc_init_reg_tables (void);
86 static int get_arc_condition_code (rtx
);
87 const struct attribute_spec arc_attribute_table
[];
88 static tree
arc_handle_interrupt_attribute (tree
*, tree
, tree
, int, bool *);
89 static bool arc_assemble_integer (rtx
, unsigned int, int);
90 static void arc_output_function_prologue (FILE *, HOST_WIDE_INT
);
91 static void arc_output_function_epilogue (FILE *, HOST_WIDE_INT
);
92 static void arc_file_start (void);
93 static void arc_internal_label (FILE *, const char *, unsigned long);
94 static void arc_setup_incoming_varargs (CUMULATIVE_ARGS
*, enum machine_mode
,
96 static bool arc_rtx_costs (rtx
, int, int, int *);
97 static int arc_address_cost (rtx
);
98 static void arc_external_libcall (rtx
);
99 static bool arc_return_in_memory (tree
, tree
);
100 static bool arc_pass_by_reference (CUMULATIVE_ARGS
*, enum machine_mode
,
103 /* Initialize the GCC target structure. */
104 #undef TARGET_ASM_ALIGNED_HI_OP
105 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
106 #undef TARGET_ASM_ALIGNED_SI_OP
107 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
108 #undef TARGET_ASM_INTEGER
109 #define TARGET_ASM_INTEGER arc_assemble_integer
111 #undef TARGET_ASM_FUNCTION_PROLOGUE
112 #define TARGET_ASM_FUNCTION_PROLOGUE arc_output_function_prologue
113 #undef TARGET_ASM_FUNCTION_EPILOGUE
114 #define TARGET_ASM_FUNCTION_EPILOGUE arc_output_function_epilogue
115 #undef TARGET_ASM_FILE_START
116 #define TARGET_ASM_FILE_START arc_file_start
117 #undef TARGET_ATTRIBUTE_TABLE
118 #define TARGET_ATTRIBUTE_TABLE arc_attribute_table
119 #undef TARGET_ASM_INTERNAL_LABEL
120 #define TARGET_ASM_INTERNAL_LABEL arc_internal_label
121 #undef TARGET_ASM_EXTERNAL_LIBCALL
122 #define TARGET_ASM_EXTERNAL_LIBCALL arc_external_libcall
124 #undef TARGET_HANDLE_OPTION
125 #define TARGET_HANDLE_OPTION arc_handle_option
127 #undef TARGET_RTX_COSTS
128 #define TARGET_RTX_COSTS arc_rtx_costs
129 #undef TARGET_ADDRESS_COST
130 #define TARGET_ADDRESS_COST arc_address_cost
132 #undef TARGET_PROMOTE_FUNCTION_ARGS
133 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
134 #undef TARGET_PROMOTE_FUNCTION_RETURN
135 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
136 #undef TARGET_PROMOTE_PROTOTYPES
137 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
139 #undef TARGET_RETURN_IN_MEMORY
140 #define TARGET_RETURN_IN_MEMORY arc_return_in_memory
141 #undef TARGET_PASS_BY_REFERENCE
142 #define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
143 #undef TARGET_CALLEE_COPIES
144 #define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
146 #undef TARGET_SETUP_INCOMING_VARARGS
147 #define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
149 struct gcc_target targetm
= TARGET_INITIALIZER
;
151 /* Implement TARGET_HANDLE_OPTION. */
154 arc_handle_option (size_t code
, const char *arg
, int value ATTRIBUTE_UNUSED
)
159 return strcmp (arg
, "base") == 0 || ARC_EXTENSION_CPU (arg
);
166 /* Called by OVERRIDE_OPTIONS to initialize various things. */
173 /* Set the pseudo-ops for the various standard sections. */
174 arc_text_section
= tmp
= xmalloc (strlen (arc_text_string
) + sizeof (ARC_SECTION_FORMAT
) + 1);
175 sprintf (tmp
, ARC_SECTION_FORMAT
, arc_text_string
);
176 arc_data_section
= tmp
= xmalloc (strlen (arc_data_string
) + sizeof (ARC_SECTION_FORMAT
) + 1);
177 sprintf (tmp
, ARC_SECTION_FORMAT
, arc_data_string
);
178 arc_rodata_section
= tmp
= xmalloc (strlen (arc_rodata_string
) + sizeof (ARC_SECTION_FORMAT
) + 1);
179 sprintf (tmp
, ARC_SECTION_FORMAT
, arc_rodata_string
);
181 arc_init_reg_tables ();
183 /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
184 memset (arc_punct_chars
, 0, sizeof (arc_punct_chars
));
185 arc_punct_chars
['#'] = 1;
186 arc_punct_chars
['*'] = 1;
187 arc_punct_chars
['?'] = 1;
188 arc_punct_chars
['!'] = 1;
189 arc_punct_chars
['~'] = 1;
192 /* The condition codes of the ARC, and the inverse function. */
193 static const char *const arc_condition_codes
[] =
195 "al", 0, "eq", "ne", "p", "n", "c", "nc", "v", "nv",
196 "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
199 #define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
201 /* Returns the index of the ARC condition code string in
202 `arc_condition_codes'. COMPARISON should be an rtx like
203 `(eq (...) (...))'. */
206 get_arc_condition_code (rtx comparison
)
208 switch (GET_CODE (comparison
))
216 case GTU
: return 14;
217 case LEU
: return 15;
220 default : gcc_unreachable ();
226 /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
227 return the mode to be used for the comparison. */
230 arc_select_cc_mode (enum rtx_code op
,
231 rtx x ATTRIBUTE_UNUSED
,
232 rtx y ATTRIBUTE_UNUSED
)
240 switch (GET_CODE (x
))
259 /* Vectors to keep interesting information about registers where it can easily
260 be got. We use to use the actual mode value as the bit number, but there
261 is (or may be) more than 32 modes now. Instead we use two tables: one
262 indexed by hard register number, and one indexed by mode. */
264 /* The purpose of arc_mode_class is to shrink the range of modes so that
265 they all fit (as bit numbers) in a 32 bit word (again). Each real mode is
266 mapped into one arc_mode_class mode. */
268 enum arc_mode_class
{
270 S_MODE
, D_MODE
, T_MODE
, O_MODE
,
271 SF_MODE
, DF_MODE
, TF_MODE
, OF_MODE
274 /* Modes for condition codes. */
275 #define C_MODES (1 << (int) C_MODE)
277 /* Modes for single-word and smaller quantities. */
278 #define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
280 /* Modes for double-word and smaller quantities. */
281 #define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
283 /* Modes for quad-word and smaller quantities. */
284 #define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
286 /* Value is 1 if register/mode pair is acceptable on arc. */
288 const unsigned int arc_hard_regno_mode_ok
[] = {
289 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
290 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
291 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, D_MODES
,
292 D_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
294 /* ??? Leave these as S_MODES for now. */
295 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
296 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
297 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
298 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, C_MODES
301 unsigned int arc_mode_class
[NUM_MACHINE_MODES
];
303 enum reg_class arc_regno_reg_class
[FIRST_PSEUDO_REGISTER
];
306 arc_init_reg_tables (void)
310 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
312 switch (GET_MODE_CLASS (i
))
315 case MODE_PARTIAL_INT
:
316 case MODE_COMPLEX_INT
:
317 if (GET_MODE_SIZE (i
) <= 4)
318 arc_mode_class
[i
] = 1 << (int) S_MODE
;
319 else if (GET_MODE_SIZE (i
) == 8)
320 arc_mode_class
[i
] = 1 << (int) D_MODE
;
321 else if (GET_MODE_SIZE (i
) == 16)
322 arc_mode_class
[i
] = 1 << (int) T_MODE
;
323 else if (GET_MODE_SIZE (i
) == 32)
324 arc_mode_class
[i
] = 1 << (int) O_MODE
;
326 arc_mode_class
[i
] = 0;
329 case MODE_COMPLEX_FLOAT
:
330 if (GET_MODE_SIZE (i
) <= 4)
331 arc_mode_class
[i
] = 1 << (int) SF_MODE
;
332 else if (GET_MODE_SIZE (i
) == 8)
333 arc_mode_class
[i
] = 1 << (int) DF_MODE
;
334 else if (GET_MODE_SIZE (i
) == 16)
335 arc_mode_class
[i
] = 1 << (int) TF_MODE
;
336 else if (GET_MODE_SIZE (i
) == 32)
337 arc_mode_class
[i
] = 1 << (int) OF_MODE
;
339 arc_mode_class
[i
] = 0;
342 arc_mode_class
[i
] = 1 << (int) C_MODE
;
345 arc_mode_class
[i
] = 0;
350 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
353 arc_regno_reg_class
[i
] = GENERAL_REGS
;
355 arc_regno_reg_class
[i
] = LPCOUNT_REG
;
357 arc_regno_reg_class
[i
] = NO_REGS
/* CC_REG: must be NO_REGS */;
359 arc_regno_reg_class
[i
] = NO_REGS
;
363 /* ARC specific attribute support.
365 The ARC has these attributes:
366 interrupt - for interrupt functions
369 const struct attribute_spec arc_attribute_table
[] =
371 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
372 { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute
},
373 { NULL
, 0, 0, false, false, false, NULL
}
376 /* Handle an "interrupt" attribute; arguments as in
377 struct attribute_spec.handler. */
379 arc_handle_interrupt_attribute (tree
*node ATTRIBUTE_UNUSED
,
382 int flags ATTRIBUTE_UNUSED
,
385 tree value
= TREE_VALUE (args
);
387 if (TREE_CODE (value
) != STRING_CST
)
389 warning (OPT_Wattributes
,
390 "argument of %qs attribute is not a string constant",
391 IDENTIFIER_POINTER (name
));
392 *no_add_attrs
= true;
394 else if (strcmp (TREE_STRING_POINTER (value
), "ilink1")
395 && strcmp (TREE_STRING_POINTER (value
), "ilink2"))
397 warning (OPT_Wattributes
,
398 "argument of %qs attribute is not \"ilink1\" or \"ilink2\"",
399 IDENTIFIER_POINTER (name
));
400 *no_add_attrs
= true;
407 /* Acceptable arguments to the call insn. */
410 call_address_operand (rtx op
, enum machine_mode mode
)
412 return (symbolic_operand (op
, mode
)
413 || (GET_CODE (op
) == CONST_INT
&& LEGITIMATE_CONSTANT_P (op
))
414 || (GET_CODE (op
) == REG
));
418 call_operand (rtx op
, enum machine_mode mode
)
420 if (GET_CODE (op
) != MEM
)
423 return call_address_operand (op
, mode
);
426 /* Returns 1 if OP is a symbol reference. */
429 symbolic_operand (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
431 switch (GET_CODE (op
))
442 /* Return truth value of statement that OP is a symbolic memory
443 operand of mode MODE. */
446 symbolic_memory_operand (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
448 if (GET_CODE (op
) == SUBREG
)
449 op
= SUBREG_REG (op
);
450 if (GET_CODE (op
) != MEM
)
453 return (GET_CODE (op
) == SYMBOL_REF
|| GET_CODE (op
) == CONST
454 || GET_CODE (op
) == LABEL_REF
);
457 /* Return true if OP is a short immediate (shimm) value. */
460 short_immediate_operand (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
462 if (GET_CODE (op
) != CONST_INT
)
464 return SMALL_INT (INTVAL (op
));
467 /* Return true if OP will require a long immediate (limm) value.
468 This is currently only used when calculating length attributes. */
471 long_immediate_operand (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
473 switch (GET_CODE (op
))
480 return !SMALL_INT (INTVAL (op
));
482 /* These can happen because large unsigned 32 bit constants are
483 represented this way (the multiplication patterns can cause these
484 to be generated). They also occur for SFmode values. */
492 /* Return true if OP is a MEM that when used as a load or store address will
493 require an 8 byte insn.
494 Load and store instructions don't allow the same possibilities but they're
495 similar enough that this one function will do.
496 This is currently only used when calculating length attributes. */
499 long_immediate_loadstore_operand (rtx op
,
500 enum machine_mode mode ATTRIBUTE_UNUSED
)
502 if (GET_CODE (op
) != MEM
)
506 switch (GET_CODE (op
))
513 /* This must be handled as "st c,[limm]". Ditto for load.
514 Technically, the assembler could translate some possibilities to
515 "st c,[limm/2 + limm/2]" if limm/2 will fit in a shimm, but we don't
516 assume that it does. */
519 /* These can happen because large unsigned 32 bit constants are
520 represented this way (the multiplication patterns can cause these
521 to be generated). They also occur for SFmode values. */
526 if (GET_CODE (XEXP (op
, 1)) == CONST_INT
527 && !SMALL_INT (INTVAL (XEXP (op
, 1))))
536 /* Return true if OP is an acceptable argument for a single word
540 move_src_operand (rtx op
, enum machine_mode mode
)
542 switch (GET_CODE (op
))
549 return (LARGE_INT (INTVAL (op
)));
551 /* We can handle DImode integer constants in SImode if the value
552 (signed or unsigned) will fit in 32 bits. This is needed because
553 large unsigned 32 bit constants are represented as CONST_DOUBLEs. */
555 return arc_double_limm_p (op
);
556 /* We can handle 32 bit floating point constants. */
558 return GET_MODE (op
) == SFmode
;
561 return register_operand (op
, mode
);
563 /* (subreg (mem ...) ...) can occur here if the inner part was once a
564 pseudo-reg and is now a stack slot. */
565 if (GET_CODE (SUBREG_REG (op
)) == MEM
)
566 return address_operand (XEXP (SUBREG_REG (op
), 0), mode
);
568 return register_operand (op
, mode
);
570 return address_operand (XEXP (op
, 0), mode
);
576 /* Return true if OP is an acceptable argument for a double word
580 move_double_src_operand (rtx op
, enum machine_mode mode
)
582 switch (GET_CODE (op
))
585 return register_operand (op
, mode
);
587 /* (subreg (mem ...) ...) can occur here if the inner part was once a
588 pseudo-reg and is now a stack slot. */
589 if (GET_CODE (SUBREG_REG (op
)) == MEM
)
590 return move_double_src_operand (SUBREG_REG (op
), mode
);
592 return register_operand (op
, mode
);
594 /* Disallow auto inc/dec for now. */
595 if (GET_CODE (XEXP (op
, 0)) == PRE_DEC
596 || GET_CODE (XEXP (op
, 0)) == PRE_INC
)
598 return address_operand (XEXP (op
, 0), mode
);
607 /* Return true if OP is an acceptable argument for a move destination. */
610 move_dest_operand (rtx op
, enum machine_mode mode
)
612 switch (GET_CODE (op
))
615 return register_operand (op
, mode
);
617 /* (subreg (mem ...) ...) can occur here if the inner part was once a
618 pseudo-reg and is now a stack slot. */
619 if (GET_CODE (SUBREG_REG (op
)) == MEM
)
620 return address_operand (XEXP (SUBREG_REG (op
), 0), mode
);
622 return register_operand (op
, mode
);
624 return address_operand (XEXP (op
, 0), mode
);
630 /* Return true if OP is valid load with update operand. */
633 load_update_operand (rtx op
, enum machine_mode mode
)
635 if (GET_CODE (op
) != MEM
636 || GET_MODE (op
) != mode
)
639 if (GET_CODE (op
) != PLUS
640 || GET_MODE (op
) != Pmode
641 || !register_operand (XEXP (op
, 0), Pmode
)
642 || !nonmemory_operand (XEXP (op
, 1), Pmode
))
647 /* Return true if OP is valid store with update operand. */
650 store_update_operand (rtx op
, enum machine_mode mode
)
652 if (GET_CODE (op
) != MEM
653 || GET_MODE (op
) != mode
)
656 if (GET_CODE (op
) != PLUS
657 || GET_MODE (op
) != Pmode
658 || !register_operand (XEXP (op
, 0), Pmode
)
659 || !(GET_CODE (XEXP (op
, 1)) == CONST_INT
660 && SMALL_INT (INTVAL (XEXP (op
, 1)))))
665 /* Return true if OP is a non-volatile non-immediate operand.
666 Volatile memory refs require a special "cache-bypass" instruction
667 and only the standard movXX patterns are set up to handle them. */
670 nonvol_nonimm_operand (rtx op
, enum machine_mode mode
)
672 if (GET_CODE (op
) == MEM
&& MEM_VOLATILE_P (op
))
674 return nonimmediate_operand (op
, mode
);
677 /* Accept integer operands in the range -0x80000000..0x7fffffff. We have
678 to check the range carefully since this predicate is used in DImode
682 const_sint32_operand (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
684 /* All allowed constants will fit a CONST_INT. */
685 return (GET_CODE (op
) == CONST_INT
686 && (INTVAL (op
) >= (-0x7fffffff - 1) && INTVAL (op
) <= 0x7fffffff));
689 /* Accept integer operands in the range 0..0xffffffff. We have to check the
690 range carefully since this predicate is used in DImode contexts. Also, we
691 need some extra crud to make it work when hosted on 64-bit machines. */
694 const_uint32_operand (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
696 #if HOST_BITS_PER_WIDE_INT > 32
697 /* All allowed constants will fit a CONST_INT. */
698 return (GET_CODE (op
) == CONST_INT
699 && (INTVAL (op
) >= 0 && INTVAL (op
) <= 0xffffffffL
));
701 return ((GET_CODE (op
) == CONST_INT
&& INTVAL (op
) >= 0)
702 || (GET_CODE (op
) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (op
) == 0));
706 /* Return 1 if OP is a comparison operator valid for the mode of CC.
707 This allows the use of MATCH_OPERATOR to recognize all the branch insns.
709 Some insns only set a few bits in the condition code. So only allow those
710 comparisons that use the bits that are valid. */
713 proper_comparison_operator (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
716 if (!COMPARISON_P (op
))
719 code
= GET_CODE (op
);
720 if (GET_MODE (XEXP (op
, 0)) == CCZNmode
)
721 return (code
== EQ
|| code
== NE
);
722 if (GET_MODE (XEXP (op
, 0)) == CCZNCmode
)
723 return (code
== EQ
|| code
== NE
724 || code
== LTU
|| code
== GEU
|| code
== GTU
|| code
== LEU
);
728 /* Misc. utilities. */
730 /* X and Y are two things to compare using CODE. Emit the compare insn and
731 return the rtx for the cc reg in the proper mode. */
734 gen_compare_reg (enum rtx_code code
, rtx x
, rtx y
)
736 enum machine_mode mode
= SELECT_CC_MODE (code
, x
, y
);
739 cc_reg
= gen_rtx_REG (mode
, 61);
741 emit_insn (gen_rtx_SET (VOIDmode
, cc_reg
,
742 gen_rtx_COMPARE (mode
, x
, y
)));
747 /* Return 1 if VALUE, a const_double, will fit in a limm (4 byte number).
748 We assume the value can be either signed or unsigned. */
751 arc_double_limm_p (rtx value
)
753 HOST_WIDE_INT low
, high
;
755 gcc_assert (GET_CODE (value
) == CONST_DOUBLE
);
757 low
= CONST_DOUBLE_LOW (value
);
758 high
= CONST_DOUBLE_HIGH (value
);
760 if (low
& 0x80000000)
762 return (((unsigned HOST_WIDE_INT
) low
<= 0xffffffff && high
== 0)
763 || (((low
& - (unsigned HOST_WIDE_INT
) 0x80000000)
764 == - (unsigned HOST_WIDE_INT
) 0x80000000)
769 return (unsigned HOST_WIDE_INT
) low
<= 0x7fffffff && high
== 0;
773 /* Do any needed setup for a variadic function. For the ARC, we must
774 create a register parameter block, and then copy any anonymous arguments
775 in registers to memory.
777 CUM has not been updated for the last named argument which has type TYPE
778 and mode MODE, and we rely on this fact.
780 We do things a little weird here. We're supposed to only allocate space
781 for the anonymous arguments. However we need to keep the stack eight byte
782 aligned. So we round the space up if necessary, and leave it to va_start
786 arc_setup_incoming_varargs (CUMULATIVE_ARGS
*cum
,
787 enum machine_mode mode
,
788 tree type ATTRIBUTE_UNUSED
,
794 /* All BLKmode values are passed by reference. */
795 gcc_assert (mode
!= BLKmode
);
797 first_anon_arg
= *cum
+ ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
800 if (first_anon_arg
< MAX_ARC_PARM_REGS
&& !no_rtl
)
802 /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
803 int first_reg_offset
= first_anon_arg
;
804 /* Size in words to "pretend" allocate. */
805 int size
= MAX_ARC_PARM_REGS
- first_reg_offset
;
806 /* Extra slop to keep stack eight byte aligned. */
807 int align_slop
= size
& 1;
810 regblock
= gen_rtx_MEM (BLKmode
,
811 plus_constant (arg_pointer_rtx
,
812 FIRST_PARM_OFFSET (0)
813 + align_slop
* UNITS_PER_WORD
));
814 set_mem_alias_set (regblock
, get_varargs_alias_set ());
815 set_mem_align (regblock
, BITS_PER_WORD
);
816 move_block_from_reg (first_reg_offset
, regblock
,
817 MAX_ARC_PARM_REGS
- first_reg_offset
);
819 *pretend_size
= ((MAX_ARC_PARM_REGS
- first_reg_offset
+ align_slop
)
824 /* Cost functions. */
826 /* Compute a (partial) cost for rtx X. Return true if the complete
827 cost has been computed, and false if subexpressions should be
828 scanned. In either case, *TOTAL contains the cost result. */
831 arc_rtx_costs (rtx x
, int code
, int outer_code ATTRIBUTE_UNUSED
, int *total
)
835 /* Small integers are as cheap as registers. 4 byte values can
836 be fetched as immediate constants - let's give that the cost
839 if (SMALL_INT (INTVAL (x
)))
849 *total
= COSTS_N_INSNS (1);
855 split_double (x
, &high
, &low
);
856 *total
= COSTS_N_INSNS (!SMALL_INT (INTVAL (high
))
857 + !SMALL_INT (INTVAL (low
)));
861 /* Encourage synth_mult to find a synthetic multiply when reasonable.
862 If we need more than 12 insns to do a multiply, then go out-of-line,
863 since the call overhead will be < 10% of the cost of the multiply. */
868 *total
= COSTS_N_INSNS (1);
869 else if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
870 *total
= COSTS_N_INSNS (16);
872 *total
= COSTS_N_INSNS (INTVAL (XEXP ((x
), 1)));
881 /* Provide the costs of an addressing mode that contains ADDR.
882 If ADDR is not a valid address, its cost is irrelevant. */
885 arc_address_cost (rtx addr
)
887 switch (GET_CODE (addr
))
899 register rtx plus0
= XEXP (addr
, 0);
900 register rtx plus1
= XEXP (addr
, 1);
902 if (GET_CODE (plus0
) != REG
)
905 switch (GET_CODE (plus1
))
908 return SMALL_INT (plus1
) ? 1 : 2;
925 /* Function prologue/epilogue handlers. */
927 /* ARC stack frames look like:
929 Before call After call
930 +-----------------------+ +-----------------------+
932 high | local variables, | | local variables, |
933 mem | reg save area, etc. | | reg save area, etc. |
935 +-----------------------+ +-----------------------+
937 | arguments on stack. | | arguments on stack. |
939 SP+16->+-----------------------+FP+48->+-----------------------+
940 | 4 word save area for | | reg parm save area, |
941 | return addr, prev %fp | | only created for |
942 SP+0->+-----------------------+ | variable argument |
944 FP+16->+-----------------------+
945 | 4 word save area for |
946 | return addr, prev %fp |
947 FP+0->+-----------------------+
951 +-----------------------+
953 | register save area |
955 +-----------------------+
957 | alloca allocations |
959 +-----------------------+
961 | arguments on stack |
963 SP+16->+-----------------------+
964 low | 4 word save area for |
965 memory | return addr, prev %fp |
966 SP+0->+-----------------------+
969 1) The "reg parm save area" does not exist for non variable argument fns.
970 The "reg parm save area" can be eliminated completely if we created our
971 own va-arc.h, but that has tradeoffs as well (so it's not done). */
973 /* Structure to be filled in by arc_compute_frame_size with register
974 save masks, and offsets for the current function. */
975 struct arc_frame_info
977 unsigned int total_size
; /* # bytes that the entire frame takes up. */
978 unsigned int extra_size
; /* # bytes of extra stuff. */
979 unsigned int pretend_size
; /* # bytes we push and pretend caller did. */
980 unsigned int args_size
; /* # bytes that outgoing arguments take up. */
981 unsigned int reg_size
; /* # bytes needed to store regs. */
982 unsigned int var_size
; /* # bytes that variables take up. */
983 unsigned int reg_offset
; /* Offset from new sp to store regs. */
984 unsigned int gmask
; /* Mask of saved gp registers. */
985 int initialized
; /* Nonzero if frame size already calculated. */
988 /* Current frame information calculated by arc_compute_frame_size. */
989 static struct arc_frame_info current_frame_info
;
991 /* Zero structure to initialize current_frame_info. */
992 static struct arc_frame_info zero_frame_info
;
994 /* Type of function DECL.
996 The result is cached. To reset the cache at the end of a function,
997 call with DECL = NULL_TREE. */
999 enum arc_function_type
1000 arc_compute_function_type (tree decl
)
1004 static enum arc_function_type fn_type
= ARC_FUNCTION_UNKNOWN
;
1005 /* Last function we were called for. */
1006 static tree last_fn
= NULL_TREE
;
1008 /* Resetting the cached value? */
1009 if (decl
== NULL_TREE
)
1011 fn_type
= ARC_FUNCTION_UNKNOWN
;
1012 last_fn
= NULL_TREE
;
1016 if (decl
== last_fn
&& fn_type
!= ARC_FUNCTION_UNKNOWN
)
1019 /* Assume we have a normal function (not an interrupt handler). */
1020 fn_type
= ARC_FUNCTION_NORMAL
;
1022 /* Now see if this is an interrupt handler. */
1023 for (a
= DECL_ATTRIBUTES (current_function_decl
);
1027 tree name
= TREE_PURPOSE (a
), args
= TREE_VALUE (a
);
1029 if (name
== get_identifier ("__interrupt__")
1030 && list_length (args
) == 1
1031 && TREE_CODE (TREE_VALUE (args
)) == STRING_CST
)
1033 tree value
= TREE_VALUE (args
);
1035 if (!strcmp (TREE_STRING_POINTER (value
), "ilink1"))
1036 fn_type
= ARC_FUNCTION_ILINK1
;
1037 else if (!strcmp (TREE_STRING_POINTER (value
), "ilink2"))
1038 fn_type
= ARC_FUNCTION_ILINK2
;
1049 #define ILINK1_REGNUM 29
1050 #define ILINK2_REGNUM 30
1051 #define RETURN_ADDR_REGNUM 31
1052 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
1053 #define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
1055 /* Tell prologue and epilogue if register REGNO should be saved / restored.
1056 The return address and frame pointer are treated separately.
1057 Don't consider them here. */
1058 #define MUST_SAVE_REGISTER(regno, interrupt_p) \
1059 ((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
1060 && (regs_ever_live[regno] && (!call_used_regs[regno] || interrupt_p)))
1062 #define MUST_SAVE_RETURN_ADDR (regs_ever_live[RETURN_ADDR_REGNUM])
1064 /* Return the bytes needed to compute the frame pointer from the current
1067 SIZE is the size needed for local variables. */
1070 arc_compute_frame_size (int size
/* # of var. bytes allocated. */)
1073 unsigned int total_size
, var_size
, args_size
, pretend_size
, extra_size
;
1074 unsigned int reg_size
, reg_offset
;
1076 enum arc_function_type fn_type
;
1080 args_size
= current_function_outgoing_args_size
;
1081 pretend_size
= current_function_pretend_args_size
;
1082 extra_size
= FIRST_PARM_OFFSET (0);
1083 total_size
= extra_size
+ pretend_size
+ args_size
+ var_size
;
1084 reg_offset
= FIRST_PARM_OFFSET(0) + current_function_outgoing_args_size
;
1088 /* See if this is an interrupt handler. Call used registers must be saved
1090 fn_type
= arc_compute_function_type (current_function_decl
);
1091 interrupt_p
= ARC_INTERRUPT_P (fn_type
);
1093 /* Calculate space needed for registers.
1094 ??? We ignore the extension registers for now. */
1096 for (regno
= 0; regno
<= 31; regno
++)
1098 if (MUST_SAVE_REGISTER (regno
, interrupt_p
))
1100 reg_size
+= UNITS_PER_WORD
;
1101 gmask
|= 1 << regno
;
1105 total_size
+= reg_size
;
1107 /* If the only space to allocate is the fp/blink save area this is an
1108 empty frame. However, if we'll be making a function call we need to
1109 allocate a stack frame for our callee's fp/blink save area. */
1110 if (total_size
== extra_size
1111 && !MUST_SAVE_RETURN_ADDR
)
1112 total_size
= extra_size
= 0;
1114 total_size
= ARC_STACK_ALIGN (total_size
);
1116 /* Save computed information. */
1117 current_frame_info
.total_size
= total_size
;
1118 current_frame_info
.extra_size
= extra_size
;
1119 current_frame_info
.pretend_size
= pretend_size
;
1120 current_frame_info
.var_size
= var_size
;
1121 current_frame_info
.args_size
= args_size
;
1122 current_frame_info
.reg_size
= reg_size
;
1123 current_frame_info
.reg_offset
= reg_offset
;
1124 current_frame_info
.gmask
= gmask
;
1125 current_frame_info
.initialized
= reload_completed
;
1127 /* Ok, we're done. */
1131 /* Common code to save/restore registers. */
1134 arc_save_restore (FILE *file
,
1135 const char *base_reg
,
1136 unsigned int offset
,
1145 for (regno
= 0; regno
<= 31; regno
++)
1147 if ((gmask
& (1L << regno
)) != 0)
1149 fprintf (file
, "\t%s %s,[%s,%d]\n",
1150 op
, reg_names
[regno
], base_reg
, offset
);
1151 offset
+= UNITS_PER_WORD
;
1156 /* Target hook to assemble an integer object. The ARC version needs to
1157 emit a special directive for references to labels and function
1161 arc_assemble_integer (rtx x
, unsigned int size
, int aligned_p
)
1163 if (size
== UNITS_PER_WORD
&& aligned_p
1164 && ((GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_FUNCTION_P (x
))
1165 || GET_CODE (x
) == LABEL_REF
))
1167 fputs ("\t.word\t%st(", asm_out_file
);
1168 output_addr_const (asm_out_file
, x
);
1169 fputs (")\n", asm_out_file
);
1172 return default_assemble_integer (x
, size
, aligned_p
);
1175 /* Set up the stack and frame pointer (if desired) for the function. */
1178 arc_output_function_prologue (FILE *file
, HOST_WIDE_INT size
)
1180 const char *sp_str
= reg_names
[STACK_POINTER_REGNUM
];
1181 const char *fp_str
= reg_names
[FRAME_POINTER_REGNUM
];
1182 unsigned int gmask
= current_frame_info
.gmask
;
1183 enum arc_function_type fn_type
= arc_compute_function_type (current_function_decl
);
1185 /* If this is an interrupt handler, set up our stack frame.
1186 ??? Optimize later. */
1187 if (ARC_INTERRUPT_P (fn_type
))
1189 fprintf (file
, "\t%s interrupt handler\n",
1191 fprintf (file
, "\tsub %s,%s,16\n", sp_str
, sp_str
);
1194 /* This is only for the human reader. */
1195 fprintf (file
, "\t%s BEGIN PROLOGUE %s vars= %d, regs= %d, args= %d, extra= %d\n",
1196 ASM_COMMENT_START
, ASM_COMMENT_START
,
1197 current_frame_info
.var_size
,
1198 current_frame_info
.reg_size
/ 4,
1199 current_frame_info
.args_size
,
1200 current_frame_info
.extra_size
);
1202 size
= ARC_STACK_ALIGN (size
);
1203 size
= (! current_frame_info
.initialized
1204 ? arc_compute_frame_size (size
)
1205 : current_frame_info
.total_size
);
1207 /* These cases shouldn't happen. Catch them now. */
1208 gcc_assert (size
|| !gmask
);
1210 /* Allocate space for register arguments if this is a variadic function. */
1211 if (current_frame_info
.pretend_size
!= 0)
1212 fprintf (file
, "\tsub %s,%s,%d\n",
1213 sp_str
, sp_str
, current_frame_info
.pretend_size
);
1215 /* The home-grown ABI says link register is saved first. */
1216 if (MUST_SAVE_RETURN_ADDR
)
1217 fprintf (file
, "\tst %s,[%s,%d]\n",
1218 reg_names
[RETURN_ADDR_REGNUM
], sp_str
, UNITS_PER_WORD
);
1220 /* Set up the previous frame pointer next (if we need to). */
1221 if (frame_pointer_needed
)
1223 fprintf (file
, "\tst %s,[%s]\n", fp_str
, sp_str
);
1224 fprintf (file
, "\tmov %s,%s\n", fp_str
, sp_str
);
1227 /* ??? We don't handle the case where the saved regs are more than 252
1228 bytes away from sp. This can be handled by decrementing sp once, saving
1229 the regs, and then decrementing it again. The epilogue doesn't have this
1230 problem as the `ld' insn takes reg+limm values (though it would be more
1231 efficient to avoid reg+limm). */
1233 /* Allocate the stack frame. */
1234 if (size
- current_frame_info
.pretend_size
> 0)
1235 fprintf (file
, "\tsub %s,%s," HOST_WIDE_INT_PRINT_DEC
"\n",
1236 sp_str
, sp_str
, size
- current_frame_info
.pretend_size
);
1238 /* Save any needed call-saved regs (and call-used if this is an
1239 interrupt handler). */
1240 arc_save_restore (file
, sp_str
, current_frame_info
.reg_offset
,
1241 /* The zeroing of these two bits is unnecessary,
1242 but leave this in for clarity. */
1243 gmask
& ~(FRAME_POINTER_MASK
| RETURN_ADDR_MASK
),
1246 fprintf (file
, "\t%s END PROLOGUE\n", ASM_COMMENT_START
);
1249 /* Do any necessary cleanup after a function to restore stack, frame,
1253 arc_output_function_epilogue (FILE *file
, HOST_WIDE_INT size
)
1255 rtx epilogue_delay
= current_function_epilogue_delay_list
;
1256 int noepilogue
= FALSE
;
1257 enum arc_function_type fn_type
= arc_compute_function_type (current_function_decl
);
1259 /* This is only for the human reader. */
1260 fprintf (file
, "\t%s EPILOGUE\n", ASM_COMMENT_START
);
1262 size
= ARC_STACK_ALIGN (size
);
1263 size
= (!current_frame_info
.initialized
1264 ? arc_compute_frame_size (size
)
1265 : current_frame_info
.total_size
);
1267 if (size
== 0 && epilogue_delay
== 0)
1269 rtx insn
= get_last_insn ();
1271 /* If the last insn was a BARRIER, we don't have to write any code
1272 because a jump (aka return) was put there. */
1273 if (GET_CODE (insn
) == NOTE
)
1274 insn
= prev_nonnote_insn (insn
);
1275 if (insn
&& GET_CODE (insn
) == BARRIER
)
1281 unsigned int pretend_size
= current_frame_info
.pretend_size
;
1282 unsigned int frame_size
= size
- pretend_size
;
1283 int restored
, fp_restored_p
;
1284 int can_trust_sp_p
= !current_function_calls_alloca
;
1285 const char *sp_str
= reg_names
[STACK_POINTER_REGNUM
];
1286 const char *fp_str
= reg_names
[FRAME_POINTER_REGNUM
];
1288 /* ??? There are lots of optimizations that can be done here.
1289 EG: Use fp to restore regs if it's closer.
1290 Maybe in time we'll do them all. For now, always restore regs from
1291 sp, but don't restore sp if we don't have to. */
1293 if (!can_trust_sp_p
)
1295 gcc_assert (frame_pointer_needed
);
1296 fprintf (file
,"\tsub %s,%s,%d\t\t%s sp not trusted here\n",
1297 sp_str
, fp_str
, frame_size
, ASM_COMMENT_START
);
1300 /* Restore any saved registers. */
1301 arc_save_restore (file
, sp_str
, current_frame_info
.reg_offset
,
1302 /* The zeroing of these two bits is unnecessary,
1303 but leave this in for clarity. */
1304 current_frame_info
.gmask
& ~(FRAME_POINTER_MASK
| RETURN_ADDR_MASK
),
1307 if (MUST_SAVE_RETURN_ADDR
)
1308 fprintf (file
, "\tld %s,[%s,%d]\n",
1309 reg_names
[RETURN_ADDR_REGNUM
],
1310 frame_pointer_needed
? fp_str
: sp_str
,
1311 UNITS_PER_WORD
+ (frame_pointer_needed
? 0 : frame_size
));
1313 /* Keep track of how much of the stack pointer we've restored.
1314 It makes the following a lot more readable. */
1318 /* We try to emit the epilogue delay slot insn right after the load
1319 of the return address register so that it can execute with the
1320 stack intact. Secondly, loads are delayed. */
1321 /* ??? If stack intactness is important, always emit now. */
1322 if (MUST_SAVE_RETURN_ADDR
&& epilogue_delay
!= NULL_RTX
)
1324 final_scan_insn (XEXP (epilogue_delay
, 0), file
, 1, 1, NULL
);
1325 epilogue_delay
= NULL_RTX
;
1328 if (frame_pointer_needed
)
1330 /* Try to restore the frame pointer in the delay slot. We can't,
1331 however, if any of these is true. */
1332 if (epilogue_delay
!= NULL_RTX
1333 || !SMALL_INT (frame_size
)
1335 || ARC_INTERRUPT_P (fn_type
))
1337 /* Note that we restore fp and sp here! */
1338 fprintf (file
, "\tld.a %s,[%s,%d]\n", fp_str
, sp_str
, frame_size
);
1339 restored
+= frame_size
;
1343 else if (!SMALL_INT (size
/* frame_size + pretend_size */)
1344 || ARC_INTERRUPT_P (fn_type
))
1346 fprintf (file
, "\tadd %s,%s,%d\n", sp_str
, sp_str
, frame_size
);
1347 restored
+= frame_size
;
1350 /* These must be done before the return insn because the delay slot
1351 does the final stack restore. */
1352 if (ARC_INTERRUPT_P (fn_type
))
1356 final_scan_insn (XEXP (epilogue_delay
, 0), file
, 1, 1, NULL
);
1360 /* Emit the return instruction. */
1362 static const int regs
[4] = {
1363 0, RETURN_ADDR_REGNUM
, ILINK1_REGNUM
, ILINK2_REGNUM
1366 /* Update the flags, if returning from an interrupt handler. */
1367 if (ARC_INTERRUPT_P (fn_type
))
1368 fprintf (file
, "\tj.d.f %s\n", reg_names
[regs
[fn_type
]]);
1370 fprintf (file
, "\tj.d %s\n", reg_names
[regs
[fn_type
]]);
1373 /* If the only register saved is the return address, we need a
1374 nop, unless we have an instruction to put into it. Otherwise
1375 we don't since reloading multiple registers doesn't reference
1376 the register being loaded. */
1378 if (ARC_INTERRUPT_P (fn_type
))
1379 fprintf (file
, "\tadd %s,%s,16\n", sp_str
, sp_str
);
1380 else if (epilogue_delay
!= NULL_RTX
)
1382 gcc_assert (!frame_pointer_needed
|| fp_restored_p
);
1383 gcc_assert (restored
>= size
);
1384 final_scan_insn (XEXP (epilogue_delay
, 0), file
, 1, 1, NULL
);
1386 else if (frame_pointer_needed
&& !fp_restored_p
)
1388 gcc_assert (SMALL_INT (frame_size
));
1389 /* Note that we restore fp and sp here! */
1390 fprintf (file
, "\tld.a %s,[%s,%d]\n", fp_str
, sp_str
, frame_size
);
1392 else if (restored
< size
)
1394 gcc_assert (SMALL_INT (size
- restored
));
1395 fprintf (file
, "\tadd %s,%s," HOST_WIDE_INT_PRINT_DEC
"\n",
1396 sp_str
, sp_str
, size
- restored
);
1399 fprintf (file
, "\tnop\n");
1402 /* Reset state info for each function. */
1403 current_frame_info
= zero_frame_info
;
1404 arc_compute_function_type (NULL_TREE
);
1407 /* Define the number of delay slots needed for the function epilogue.
1409 Interrupt handlers can't have any epilogue delay slots (it's always needed
1410 for something else, I think). For normal functions, we have to worry about
1411 using call-saved regs as they'll be restored before the delay slot insn.
1412 Functions with non-empty frames already have enough choices for the epilogue
1413 delay slot so for now we only consider functions with empty frames. */
1416 arc_delay_slots_for_epilogue (void)
1418 if (arc_compute_function_type (current_function_decl
) != ARC_FUNCTION_NORMAL
)
1420 if (!current_frame_info
.initialized
)
1421 (void) arc_compute_frame_size (get_frame_size ());
1422 if (current_frame_info
.total_size
== 0)
1427 /* Return true if TRIAL is a valid insn for the epilogue delay slot.
1428 Any single length instruction which doesn't reference the stack or frame
1429 pointer or any call-saved register is OK. SLOT will always be 0. */
1432 arc_eligible_for_epilogue_delay (rtx trial
, int slot
)
1436 if (get_attr_length (trial
) == 1
1437 /* If registers where saved, presumably there's more than enough
1438 possibilities for the delay slot. The alternative is something
1439 more complicated (of course, if we expanded the epilogue as rtl
1440 this problem would go away). */
1441 /* ??? Note that this will always be true since only functions with
1442 empty frames have epilogue delay slots. See
1443 arc_delay_slots_for_epilogue. */
1444 && current_frame_info
.gmask
== 0
1445 && ! reg_mentioned_p (stack_pointer_rtx
, PATTERN (trial
))
1446 && ! reg_mentioned_p (frame_pointer_rtx
, PATTERN (trial
)))
1451 /* Return true if OP is a shift operator. */
1454 shift_operator (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
1456 switch (GET_CODE (op
))
1467 /* Output the assembler code for doing a shift.
1468 We go to a bit of trouble to generate efficient code as the ARC only has
1469 single bit shifts. This is taken from the h8300 port. We only have one
1470 mode of shifting and can't access individual bytes like the h8300 can, so
1471 this is greatly simplified (at the expense of not generating hyper-
1474 This function is not used if the variable shift insns are present. */
1476 /* ??? We assume the output operand is the same as operand 1.
1477 This can be optimized (deleted) in the case of 1 bit shifts. */
1478 /* ??? We use the loop register here. We don't use it elsewhere (yet) and
1479 using it here will give us a chance to play with it. */
1482 output_shift (rtx
*operands
)
1484 rtx shift
= operands
[3];
1485 enum machine_mode mode
= GET_MODE (shift
);
1486 enum rtx_code code
= GET_CODE (shift
);
1487 const char *shift_one
;
1489 gcc_assert (mode
== SImode
);
1493 case ASHIFT
: shift_one
= "asl %0,%0"; break;
1494 case ASHIFTRT
: shift_one
= "asr %0,%0"; break;
1495 case LSHIFTRT
: shift_one
= "lsr %0,%0"; break;
1496 default: gcc_unreachable ();
1499 if (GET_CODE (operands
[2]) != CONST_INT
)
1503 output_asm_insn ("sub.f 0,%2,0", operands
);
1504 output_asm_insn ("mov lp_count,%2", operands
);
1505 output_asm_insn ("bz 2f", operands
);
1508 output_asm_insn ("mov %4,%2", operands
);
1513 int n
= INTVAL (operands
[2]);
1515 /* If the count is negative, make it 0. */
1518 /* If the count is too big, truncate it.
1519 ANSI says shifts of GET_MODE_BITSIZE are undefined - we choose to
1520 do the intuitive thing. */
1521 else if (n
> GET_MODE_BITSIZE (mode
))
1522 n
= GET_MODE_BITSIZE (mode
);
1524 /* First see if we can do them inline. */
1528 output_asm_insn (shift_one
, operands
);
1530 /* See if we can use a rotate/and. */
1531 else if (n
== BITS_PER_WORD
- 1)
1536 output_asm_insn ("and %0,%0,1\n\tror %0,%0", operands
);
1539 /* The ARC doesn't have a rol insn. Use something else. */
1540 output_asm_insn ("asl.f 0,%0\n\tsbc %0,0,0", operands
);
1543 /* The ARC doesn't have a rol insn. Use something else. */
1544 output_asm_insn ("asl.f 0,%0\n\tadc %0,0,0", operands
);
1556 output_asm_insn ("mov lp_count,%c2", operands
);
1558 output_asm_insn ("mov %4,%c2", operands
);
1563 sprintf (buf
, "lr %%4,[status]\n\tadd %%4,%%4,6\t%s single insn loop start",
1566 sprintf (buf
, "mov %%4,%%%%st(1f)\t%s (single insn loop start) >> 2",
1568 output_asm_insn (buf
, operands
);
1569 output_asm_insn ("sr %4,[lp_start]", operands
);
1570 output_asm_insn ("add %4,%4,1", operands
);
1571 output_asm_insn ("sr %4,[lp_end]", operands
);
1572 output_asm_insn ("nop\n\tnop", operands
);
1574 fprintf (asm_out_file
, "\t%s single insn loop\n",
1577 fprintf (asm_out_file
, "1:\t%s single insn loop\n",
1579 output_asm_insn (shift_one
, operands
);
1580 fprintf (asm_out_file
, "2:\t%s end single insn loop\n",
1585 fprintf (asm_out_file
, "1:\t%s begin shift loop\n",
1587 output_asm_insn ("sub.f %4,%4,1", operands
);
1588 output_asm_insn ("nop", operands
);
1589 output_asm_insn ("bn.nd 2f", operands
);
1590 output_asm_insn (shift_one
, operands
);
1591 output_asm_insn ("b.nd 1b", operands
);
1592 fprintf (asm_out_file
, "2:\t%s end shift loop\n",
1601 /* Nested function support. */
1603 /* Emit RTL insns to initialize the variable parts of a trampoline.
1604 FNADDR is an RTX for the address of the function's pure code.
1605 CXT is an RTX for the static chain value for the function. */
1608 arc_initialize_trampoline (rtx tramp ATTRIBUTE_UNUSED
,
1609 rtx fnaddr ATTRIBUTE_UNUSED
,
1610 rtx cxt ATTRIBUTE_UNUSED
)
1614 /* Set the cpu type and print out other fancy things,
1615 at the top of the file. */
1618 arc_file_start (void)
1620 default_file_start ();
1621 fprintf (asm_out_file
, "\t.cpu %s\n", arc_cpu_string
);
1624 /* Print operand X (an rtx) in assembler syntax to file FILE.
1625 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
1626 For `%' followed by punctuation, CODE is the punctuation and X is null. */
1629 arc_print_operand (FILE *file
, rtx x
, int code
)
1634 /* Conditional branches. For now these are equivalent. */
1636 /* Unconditional branches. Output the appropriate delay slot suffix. */
1637 if (!final_sequence
|| XVECLEN (final_sequence
, 0) == 1)
1639 /* There's nothing in the delay slot. */
1640 fputs (".nd", file
);
1644 rtx jump
= XVECEXP (final_sequence
, 0, 0);
1645 rtx delay
= XVECEXP (final_sequence
, 0, 1);
1646 if (INSN_ANNULLED_BRANCH_P (jump
))
1647 fputs (INSN_FROM_TARGET_P (delay
) ? ".jd" : ".nd", file
);
1652 case '?' : /* with leading "." */
1653 case '!' : /* without leading "." */
1654 /* This insn can be conditionally executed. See if the ccfsm machinery
1655 says it should be conditionalized. */
1656 if (arc_ccfsm_state
== 3 || arc_ccfsm_state
== 4)
1658 /* Is this insn in a delay slot? */
1659 if (final_sequence
&& XVECLEN (final_sequence
, 0) == 2)
1661 rtx insn
= XVECEXP (final_sequence
, 0, 1);
1663 /* If the insn is annulled and is from the target path, we need
1664 to inverse the condition test. */
1665 if (INSN_ANNULLED_BRANCH_P (insn
))
1667 if (INSN_FROM_TARGET_P (insn
))
1668 fprintf (file
, "%s%s",
1669 code
== '?' ? "." : "",
1670 arc_condition_codes
[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current_cc
)]);
1672 fprintf (file
, "%s%s",
1673 code
== '?' ? "." : "",
1674 arc_condition_codes
[arc_ccfsm_current_cc
]);
1678 /* This insn is executed for either path, so don't
1679 conditionalize it at all. */
1680 ; /* nothing to do */
1685 /* This insn isn't in a delay slot. */
1686 fprintf (file
, "%s%s",
1687 code
== '?' ? "." : "",
1688 arc_condition_codes
[arc_ccfsm_current_cc
]);
1693 /* Output a nop if we're between a set of the condition codes,
1694 and a conditional branch. */
1695 if (last_insn_set_cc_p
)
1696 fputs ("nop\n\t", file
);
1699 fputs (arc_condition_codes
[get_arc_condition_code (x
)], file
);
1702 fputs (arc_condition_codes
[ARC_INVERSE_CONDITION_CODE
1703 (get_arc_condition_code (x
))],
1707 /* Write second word of DImode or DFmode reference,
1708 register or memory. */
1709 if (GET_CODE (x
) == REG
)
1710 fputs (reg_names
[REGNO (x
)+1], file
);
1711 else if (GET_CODE (x
) == MEM
)
1714 /* Handle possible auto-increment. Since it is pre-increment and
1715 we have already done it, we can just use an offset of four. */
1716 /* ??? This is taken from rs6000.c I think. I don't think it is
1717 currently necessary, but keep it around. */
1718 if (GET_CODE (XEXP (x
, 0)) == PRE_INC
1719 || GET_CODE (XEXP (x
, 0)) == PRE_DEC
)
1720 output_address (plus_constant (XEXP (XEXP (x
, 0), 0), 4));
1722 output_address (plus_constant (XEXP (x
, 0), 4));
1726 output_operand_lossage ("invalid operand to %%R code");
1729 if ((GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_FUNCTION_P (x
))
1730 || GET_CODE (x
) == LABEL_REF
)
1732 fprintf (file
, "%%st(");
1733 output_addr_const (file
, x
);
1734 fprintf (file
, ")");
1740 if (GET_CODE (x
) == REG
)
1742 /* L = least significant word, H = most significant word */
1743 if ((TARGET_BIG_ENDIAN
!= 0) ^ (code
== 'L'))
1744 fputs (reg_names
[REGNO (x
)], file
);
1746 fputs (reg_names
[REGNO (x
)+1], file
);
1748 else if (GET_CODE (x
) == CONST_INT
1749 || GET_CODE (x
) == CONST_DOUBLE
)
1753 split_double (x
, &first
, &second
);
1754 fprintf (file
, "0x%08lx",
1755 (long)(code
== 'L' ? INTVAL (first
) : INTVAL (second
)));
1758 output_operand_lossage ("invalid operand to %%H/%%L code");
1764 gcc_assert (GET_CODE (x
) == CONST_DOUBLE
1765 && GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
);
1767 real_to_decimal (str
, CONST_DOUBLE_REAL_VALUE (x
), sizeof (str
), 0, 1);
1768 fprintf (file
, "%s", str
);
1772 /* Output a load/store with update indicator if appropriate. */
1773 if (GET_CODE (x
) == MEM
)
1775 if (GET_CODE (XEXP (x
, 0)) == PRE_INC
1776 || GET_CODE (XEXP (x
, 0)) == PRE_DEC
)
1780 output_operand_lossage ("invalid operand to %%U code");
1783 /* Output cache bypass indicator for a load/store insn. Volatile memory
1784 refs are defined to use the cache bypass mechanism. */
1785 if (GET_CODE (x
) == MEM
)
1787 if (MEM_VOLATILE_P (x
))
1788 fputs (".di", file
);
1791 output_operand_lossage ("invalid operand to %%V code");
1794 /* Do nothing special. */
1798 output_operand_lossage ("invalid operand output code");
1801 switch (GET_CODE (x
))
1804 fputs (reg_names
[REGNO (x
)], file
);
1808 if (GET_CODE (XEXP (x
, 0)) == PRE_INC
)
1809 output_address (plus_constant (XEXP (XEXP (x
, 0), 0),
1810 GET_MODE_SIZE (GET_MODE (x
))));
1811 else if (GET_CODE (XEXP (x
, 0)) == PRE_DEC
)
1812 output_address (plus_constant (XEXP (XEXP (x
, 0), 0),
1813 - GET_MODE_SIZE (GET_MODE (x
))));
1815 output_address (XEXP (x
, 0));
1819 /* We handle SFmode constants here as output_addr_const doesn't. */
1820 if (GET_MODE (x
) == SFmode
)
1825 REAL_VALUE_FROM_CONST_DOUBLE (d
, x
);
1826 REAL_VALUE_TO_TARGET_SINGLE (d
, l
);
1827 fprintf (file
, "0x%08lx", l
);
1830 /* Fall through. Let output_addr_const deal with it. */
1832 output_addr_const (file
, x
);
1837 /* Print a memory address as an operand to reference that memory location. */
1840 arc_print_operand_address (FILE *file
, rtx addr
)
1842 register rtx base
, index
= 0;
1845 switch (GET_CODE (addr
))
1848 fputs (reg_names
[REGNO (addr
)], file
);
1851 if (/*???*/ 0 && SYMBOL_REF_FUNCTION_P (addr
))
1853 fprintf (file
, "%%st(");
1854 output_addr_const (file
, addr
);
1855 fprintf (file
, ")");
1858 output_addr_const (file
, addr
);
1861 if (GET_CODE (XEXP (addr
, 0)) == CONST_INT
)
1862 offset
= INTVAL (XEXP (addr
, 0)), base
= XEXP (addr
, 1);
1863 else if (GET_CODE (XEXP (addr
, 1)) == CONST_INT
)
1864 offset
= INTVAL (XEXP (addr
, 1)), base
= XEXP (addr
, 0);
1866 base
= XEXP (addr
, 0), index
= XEXP (addr
, 1);
1867 gcc_assert (GET_CODE (base
) == REG
);
1868 fputs (reg_names
[REGNO (base
)], file
);
1872 fprintf (file
, ",%d", offset
);
1876 switch (GET_CODE (index
))
1879 fprintf (file
, ",%s", reg_names
[REGNO (index
)]);
1882 fputc (',', file
), output_addr_const (file
, index
);
1891 /* We shouldn't get here as we've lost the mode of the memory object
1892 (which says how much to inc/dec by. */
1896 output_addr_const (file
, addr
);
1901 /* Update compare/branch separation marker. */
1904 record_cc_ref (rtx insn
)
1906 last_insn_set_cc_p
= current_insn_set_cc_p
;
1908 switch (get_attr_cond (insn
))
1913 if (get_attr_length (insn
) == 1)
1914 current_insn_set_cc_p
= 1;
1916 current_insn_set_cc_p
= 0;
1919 current_insn_set_cc_p
= 0;
1924 /* Conditional execution support.
1926 This is based on the ARM port but for now is much simpler.
1928 A finite state machine takes care of noticing whether or not instructions
1929 can be conditionally executed, and thus decrease execution time and code
1930 size by deleting branch instructions. The fsm is controlled by
1931 final_prescan_insn, and controls the actions of PRINT_OPERAND. The patterns
1932 in the .md file for the branch insns also have a hand in this. */
1934 /* The state of the fsm controlling condition codes are:
1935 0: normal, do nothing special
1936 1: don't output this insn
1937 2: don't output this insn
1938 3: make insns conditional
1939 4: make insns conditional
1941 State transitions (state->state by whom, under what condition):
1942 0 -> 1 final_prescan_insn, if insn is conditional branch
1943 0 -> 2 final_prescan_insn, if the `target' is an unconditional branch
1944 1 -> 3 branch patterns, after having not output the conditional branch
1945 2 -> 4 branch patterns, after having not output the conditional branch
1946 3 -> 0 (*targetm.asm_out.internal_label), if the `target' label is reached
1947 (the target label has CODE_LABEL_NUMBER equal to
1948 arc_ccfsm_target_label).
1949 4 -> 0 final_prescan_insn, if `target' unconditional branch is reached
1951 If the jump clobbers the conditions then we use states 2 and 4.
1953 A similar thing can be done with conditional return insns.
1955 We also handle separating branches from sets of the condition code.
1956 This is done here because knowledge of the ccfsm state is required,
1957 we may not be outputting the branch. */
1960 arc_final_prescan_insn (rtx insn
,
1961 rtx
*opvec ATTRIBUTE_UNUSED
,
1962 int noperands ATTRIBUTE_UNUSED
)
1964 /* BODY will hold the body of INSN. */
1965 register rtx body
= PATTERN (insn
);
1967 /* This will be 1 if trying to repeat the trick (i.e.: do the `else' part of
1968 an if/then/else), and things need to be reversed. */
1971 /* If we start with a return insn, we only succeed if we find another one. */
1972 int seeking_return
= 0;
1974 /* START_INSN will hold the insn from where we start looking. This is the
1975 first insn after the following code_label if REVERSE is true. */
1976 rtx start_insn
= insn
;
1978 /* Update compare/branch separation marker. */
1979 record_cc_ref (insn
);
1981 /* Allow -mdebug-ccfsm to turn this off so we can see how well it does.
1982 We can't do this in macro FINAL_PRESCAN_INSN because its called from
1983 final_scan_insn which has `optimize' as a local. */
1984 if (optimize
< 2 || TARGET_NO_COND_EXEC
)
1987 /* If in state 4, check if the target branch is reached, in order to
1988 change back to state 0. */
1989 if (arc_ccfsm_state
== 4)
1991 if (insn
== arc_ccfsm_target_insn
)
1993 arc_ccfsm_target_insn
= NULL
;
1994 arc_ccfsm_state
= 0;
1999 /* If in state 3, it is possible to repeat the trick, if this insn is an
2000 unconditional branch to a label, and immediately following this branch
2001 is the previous target label which is only used once, and the label this
2002 branch jumps to is not too far off. Or in other words "we've done the
2003 `then' part, see if we can do the `else' part." */
2004 if (arc_ccfsm_state
== 3)
2006 if (simplejump_p (insn
))
2008 start_insn
= next_nonnote_insn (start_insn
);
2009 if (GET_CODE (start_insn
) == BARRIER
)
2011 /* ??? Isn't this always a barrier? */
2012 start_insn
= next_nonnote_insn (start_insn
);
2014 if (GET_CODE (start_insn
) == CODE_LABEL
2015 && CODE_LABEL_NUMBER (start_insn
) == arc_ccfsm_target_label
2016 && LABEL_NUSES (start_insn
) == 1)
2021 else if (GET_CODE (body
) == RETURN
)
2023 start_insn
= next_nonnote_insn (start_insn
);
2024 if (GET_CODE (start_insn
) == BARRIER
)
2025 start_insn
= next_nonnote_insn (start_insn
);
2026 if (GET_CODE (start_insn
) == CODE_LABEL
2027 && CODE_LABEL_NUMBER (start_insn
) == arc_ccfsm_target_label
2028 && LABEL_NUSES (start_insn
) == 1)
2040 if (GET_CODE (insn
) != JUMP_INSN
)
2043 /* This jump might be paralleled with a clobber of the condition codes,
2044 the jump should always come first. */
2045 if (GET_CODE (body
) == PARALLEL
&& XVECLEN (body
, 0) > 0)
2046 body
= XVECEXP (body
, 0, 0);
2049 || (GET_CODE (body
) == SET
&& GET_CODE (SET_DEST (body
)) == PC
2050 && GET_CODE (SET_SRC (body
)) == IF_THEN_ELSE
))
2052 int insns_skipped
= 0, fail
= FALSE
, succeed
= FALSE
;
2053 /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
2054 int then_not_else
= TRUE
;
2055 /* Nonzero if next insn must be the target label. */
2056 int next_must_be_target_label_p
;
2057 rtx this_insn
= start_insn
, label
= 0;
2059 /* Register the insn jumped to. */
2062 if (!seeking_return
)
2063 label
= XEXP (SET_SRC (body
), 0);
2065 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == LABEL_REF
)
2066 label
= XEXP (XEXP (SET_SRC (body
), 1), 0);
2067 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == LABEL_REF
)
2069 label
= XEXP (XEXP (SET_SRC (body
), 2), 0);
2070 then_not_else
= FALSE
;
2072 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == RETURN
)
2074 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == RETURN
)
2077 then_not_else
= FALSE
;
2082 /* See how many insns this branch skips, and what kind of insns. If all
2083 insns are okay, and the label or unconditional branch to the same
2084 label is not too far away, succeed. */
2085 for (insns_skipped
= 0, next_must_be_target_label_p
= FALSE
;
2086 !fail
&& !succeed
&& insns_skipped
< MAX_INSNS_SKIPPED
;
2091 this_insn
= next_nonnote_insn (this_insn
);
2095 if (next_must_be_target_label_p
)
2097 if (GET_CODE (this_insn
) == BARRIER
)
2099 if (GET_CODE (this_insn
) == CODE_LABEL
2100 && this_insn
== label
)
2102 arc_ccfsm_state
= 1;
2110 scanbody
= PATTERN (this_insn
);
2112 switch (GET_CODE (this_insn
))
2115 /* Succeed if it is the target label, otherwise fail since
2116 control falls in from somewhere else. */
2117 if (this_insn
== label
)
2119 arc_ccfsm_state
= 1;
2127 /* Succeed if the following insn is the target label.
2129 If return insns are used then the last insn in a function
2130 will be a barrier. */
2131 next_must_be_target_label_p
= TRUE
;
2135 /* Can handle a call insn if there are no insns after it.
2136 IE: The next "insn" is the target label. We don't have to
2137 worry about delay slots as such insns are SEQUENCE's inside
2138 INSN's. ??? It is possible to handle such insns though. */
2139 if (get_attr_cond (this_insn
) == COND_CANUSE
)
2140 next_must_be_target_label_p
= TRUE
;
2146 /* If this is an unconditional branch to the same label, succeed.
2147 If it is to another label, do nothing. If it is conditional,
2149 /* ??? Probably, the test for the SET and the PC are unnecessary. */
2151 if (GET_CODE (scanbody
) == SET
2152 && GET_CODE (SET_DEST (scanbody
)) == PC
)
2154 if (GET_CODE (SET_SRC (scanbody
)) == LABEL_REF
2155 && XEXP (SET_SRC (scanbody
), 0) == label
&& !reverse
)
2157 arc_ccfsm_state
= 2;
2160 else if (GET_CODE (SET_SRC (scanbody
)) == IF_THEN_ELSE
)
2163 else if (GET_CODE (scanbody
) == RETURN
2166 arc_ccfsm_state
= 2;
2169 else if (GET_CODE (scanbody
) == PARALLEL
)
2171 if (get_attr_cond (this_insn
) != COND_CANUSE
)
2177 /* We can only do this with insns that can use the condition
2178 codes (and don't set them). */
2179 if (GET_CODE (scanbody
) == SET
2180 || GET_CODE (scanbody
) == PARALLEL
)
2182 if (get_attr_cond (this_insn
) != COND_CANUSE
)
2185 /* We can't handle other insns like sequences. */
2197 if ((!seeking_return
) && (arc_ccfsm_state
== 1 || reverse
))
2198 arc_ccfsm_target_label
= CODE_LABEL_NUMBER (label
);
2201 gcc_assert (seeking_return
|| arc_ccfsm_state
== 2);
2202 while (this_insn
&& GET_CODE (PATTERN (this_insn
)) == USE
)
2204 this_insn
= next_nonnote_insn (this_insn
);
2205 gcc_assert (!this_insn
2206 || (GET_CODE (this_insn
) != BARRIER
2207 && GET_CODE (this_insn
) != CODE_LABEL
));
2211 /* Oh dear! we ran off the end, give up. */
2212 extract_insn_cached (insn
);
2213 arc_ccfsm_state
= 0;
2214 arc_ccfsm_target_insn
= NULL
;
2217 arc_ccfsm_target_insn
= this_insn
;
2220 /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
2223 arc_ccfsm_current_cc
= get_arc_condition_code (XEXP (SET_SRC (body
),
2226 if (reverse
|| then_not_else
)
2227 arc_ccfsm_current_cc
= ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current_cc
);
2230 /* Restore recog_data. Getting the attributes of other insns can
2231 destroy this array, but final.c assumes that it remains intact
2232 across this call. */
2233 extract_insn_cached (insn
);
2237 /* Record that we are currently outputting label NUM with prefix PREFIX.
2238 It it's the label we're looking for, reset the ccfsm machinery.
2240 Called from (*targetm.asm_out.internal_label). */
2243 arc_ccfsm_at_label (const char *prefix
, int num
)
2245 if (arc_ccfsm_state
== 3 && arc_ccfsm_target_label
== num
2246 && !strcmp (prefix
, "L"))
2248 arc_ccfsm_state
= 0;
2249 arc_ccfsm_target_insn
= NULL_RTX
;
2253 /* See if the current insn, which is a conditional branch, is to be
2257 arc_ccfsm_branch_deleted_p (void)
2259 if (arc_ccfsm_state
== 1 || arc_ccfsm_state
== 2)
2264 /* Record a branch isn't output because subsequent insns can be
2268 arc_ccfsm_record_branch_deleted (void)
2270 /* Indicate we're conditionalizing insns now. */
2271 arc_ccfsm_state
+= 2;
2273 /* If the next insn is a subroutine call, we still need a nop between the
2274 cc setter and user. We need to undo the effect of calling record_cc_ref
2275 for the just deleted branch. */
2276 current_insn_set_cc_p
= last_insn_set_cc_p
;
2280 arc_va_start (tree valist
, rtx nextarg
)
2282 /* See arc_setup_incoming_varargs for reasons for this oddity. */
2283 if (current_function_args_info
< 8
2284 && (current_function_args_info
& 1))
2285 nextarg
= plus_constant (nextarg
, UNITS_PER_WORD
);
2287 std_expand_builtin_va_start (valist
, nextarg
);
2290 /* This is how to output a definition of an internal numbered label where
2291 PREFIX is the class of label and NUM is the number within the class. */
2294 arc_internal_label (FILE *stream
, const char *prefix
, unsigned long labelno
)
2296 arc_ccfsm_at_label (prefix
, labelno
);
2297 default_internal_label (stream
, prefix
, labelno
);
2300 /* Worker function for TARGET_ASM_EXTERNAL_LIBCALL. */
2303 arc_external_libcall (rtx fun ATTRIBUTE_UNUSED
)
2306 /* On the ARC we want to have libgcc's for multiple cpus in one binary.
2307 We can't use `assemble_name' here as that will call ASM_OUTPUT_LABELREF
2308 and we'll get another suffix added on if -mmangle-cpu. */
2309 if (TARGET_MANGLE_CPU_LIBGCC
)
2311 fprintf (FILE, "\t.rename\t_%s, _%s%s\n",
2312 XSTR (SYMREF
, 0), XSTR (SYMREF
, 0),
2318 /* Worker function for TARGET_RETURN_IN_MEMORY. */
2321 arc_return_in_memory (tree type
, tree fntype ATTRIBUTE_UNUSED
)
2323 if (AGGREGATE_TYPE_P (type
))
2327 HOST_WIDE_INT size
= int_size_in_bytes (type
);
2328 return (size
== -1 || size
> 8);
2332 /* For ARC, All aggregates and arguments greater than 8 bytes are
2333 passed by reference. */
2336 arc_pass_by_reference (CUMULATIVE_ARGS
*ca ATTRIBUTE_UNUSED
,
2337 enum machine_mode mode
, tree type
,
2338 bool named ATTRIBUTE_UNUSED
)
2340 unsigned HOST_WIDE_INT size
;
2344 if (AGGREGATE_TYPE_P (type
))
2346 size
= int_size_in_bytes (type
);
2349 size
= GET_MODE_SIZE (mode
);