1 /* Definitions for Toshiba Media Processor
2 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
3 Free Software Foundation, Inc.
4 Contributed by Red Hat, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
24 #include "coretypes.h"
29 #include "hard-reg-set.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "insn-flags.h"
35 #include "insn-attr.h"
48 #include "integrate.h"
50 #include "target-def.h"
51 #include "langhooks.h"
54 /* Structure of this file:
56 + Command Line Option Support
57 + Pattern support - constraints, predicates, expanders
60 + Functions to save and restore machine-specific function data.
61 + Frame/Epilog/Prolog Related
63 + Function args in registers
64 + Handle pipeline hazards
67 + Machine-dependent Reorg
72 Symbols are encoded as @ <char> . <name> where <char> is one of these:
80 c - cb (control bus) */
82 struct GTY(()) machine_function
84 int mep_frame_pointer_needed;
92 /* Records __builtin_return address. */
96 int reg_save_slot[FIRST_PSEUDO_REGISTER];
97 unsigned char reg_saved[FIRST_PSEUDO_REGISTER];
99 /* 2 if the current function has an interrupt attribute, 1 if not, 0
100 if unknown. This is here because resource.c uses EPILOGUE_USES
102 int interrupt_handler;
104 /* Likewise, for disinterrupt attribute. */
105 int disable_interrupts;
107 /* Number of doloop tags used so far. */
110 /* True if the last tag was allocated to a doloop_end. */
111 bool doloop_tag_from_end;
113 /* True if reload changes $TP. */
114 bool reload_changes_tp;
116 /* 2 if there are asm()s without operands, 1 if not, 0 if unknown.
117 We only set this if the function is an interrupt handler. */
118 int asms_without_operands;
121 #define MEP_CONTROL_REG(x) \
122 (GET_CODE (x) == REG && ANY_CONTROL_REGNO_P (REGNO (x)))
124 static const struct attribute_spec mep_attribute_table[11];
126 static GTY(()) section * based_section;
127 static GTY(()) section * tinybss_section;
128 static GTY(()) section * far_section;
129 static GTY(()) section * farbss_section;
130 static GTY(()) section * frodata_section;
131 static GTY(()) section * srodata_section;
133 static GTY(()) section * vtext_section;
134 static GTY(()) section * vftext_section;
135 static GTY(()) section * ftext_section;
137 static void mep_set_leaf_registers (int);
138 static bool symbol_p (rtx);
139 static bool symbolref_p (rtx);
140 static void encode_pattern_1 (rtx);
141 static void encode_pattern (rtx);
142 static bool const_in_range (rtx, int, int);
143 static void mep_rewrite_mult (rtx, rtx);
144 static void mep_rewrite_mulsi3 (rtx, rtx, rtx, rtx);
145 static void mep_rewrite_maddsi3 (rtx, rtx, rtx, rtx, rtx);
146 static bool mep_reuse_lo_p_1 (rtx, rtx, rtx, bool);
147 static bool move_needs_splitting (rtx, rtx, enum machine_mode);
148 static bool mep_expand_setcc_1 (enum rtx_code, rtx, rtx, rtx);
149 static bool mep_nongeneral_reg (rtx);
150 static bool mep_general_copro_reg (rtx);
151 static bool mep_nonregister (rtx);
152 static struct machine_function* mep_init_machine_status (void);
153 static rtx mep_tp_rtx (void);
154 static rtx mep_gp_rtx (void);
155 static bool mep_interrupt_p (void);
156 static bool mep_disinterrupt_p (void);
157 static bool mep_reg_set_p (rtx, rtx);
158 static bool mep_reg_set_in_function (int);
159 static bool mep_interrupt_saved_reg (int);
160 static bool mep_call_saves_register (int);
162 static void add_constant (int, int, int, int);
163 static bool mep_function_uses_sp (void);
164 static rtx maybe_dead_move (rtx, rtx, bool);
165 static void mep_reload_pointer (int, const char *);
166 static void mep_start_function (FILE *, HOST_WIDE_INT);
167 static bool mep_function_ok_for_sibcall (tree, tree);
168 static int unique_bit_in (HOST_WIDE_INT);
169 static int bit_size_for_clip (HOST_WIDE_INT);
170 static int bytesize (const_tree, enum machine_mode);
171 static tree mep_validate_based_tiny (tree *, tree, tree, int, bool *);
172 static tree mep_validate_near_far (tree *, tree, tree, int, bool *);
173 static tree mep_validate_disinterrupt (tree *, tree, tree, int, bool *);
174 static tree mep_validate_interrupt (tree *, tree, tree, int, bool *);
175 static tree mep_validate_io_cb (tree *, tree, tree, int, bool *);
176 static tree mep_validate_vliw (tree *, tree, tree, int, bool *);
177 static bool mep_function_attribute_inlinable_p (const_tree);
178 static bool mep_can_inline_p (tree, tree);
179 static bool mep_lookup_pragma_disinterrupt (const char *);
180 static int mep_multiple_address_regions (tree, bool);
181 static int mep_attrlist_to_encoding (tree, tree);
182 static void mep_insert_attributes (tree, tree *);
183 static void mep_encode_section_info (tree, rtx, int);
184 static section * mep_select_section (tree, int, unsigned HOST_WIDE_INT);
185 static void mep_unique_section (tree, int);
186 static unsigned int mep_section_type_flags (tree, const char *, int);
187 static void mep_asm_named_section (const char *, unsigned int, tree);
188 static bool mep_mentioned_p (rtx, rtx, int);
189 static void mep_reorg_regmove (rtx);
190 static rtx mep_insert_repeat_label_last (rtx, rtx, bool, bool);
191 static void mep_reorg_repeat (rtx);
192 static bool mep_invertable_branch_p (rtx);
193 static void mep_invert_branch (rtx, rtx);
194 static void mep_reorg_erepeat (rtx);
195 static void mep_jmp_return_reorg (rtx);
196 static void mep_reorg_addcombine (rtx);
197 static void mep_reorg (void);
198 static void mep_init_intrinsics (void);
199 static void mep_init_builtins (void);
200 static void mep_intrinsic_unavailable (int);
201 static bool mep_get_intrinsic_insn (int, const struct cgen_insn **);
202 static bool mep_get_move_insn (int, const struct cgen_insn **);
203 static rtx mep_convert_arg (enum machine_mode, rtx);
204 static rtx mep_convert_regnum (const struct cgen_regnum_operand *, rtx);
205 static rtx mep_legitimize_arg (const struct insn_operand_data *, rtx, int);
206 static void mep_incompatible_arg (const struct insn_operand_data *, rtx, int, tree);
207 static rtx mep_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
208 static int mep_adjust_cost (rtx, rtx, rtx, int);
209 static int mep_issue_rate (void);
210 static rtx mep_find_ready_insn (rtx *, int, enum attr_slot, int);
211 static void mep_move_ready_insn (rtx *, int, rtx);
212 static int mep_sched_reorder (FILE *, int, rtx *, int *, int);
213 static rtx mep_make_bundle (rtx, rtx);
214 static void mep_bundle_insns (rtx);
215 static bool mep_rtx_cost (rtx, int, int, int *, bool);
216 static int mep_address_cost (rtx, bool);
217 static void mep_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
219 static bool mep_pass_by_reference (CUMULATIVE_ARGS * cum, enum machine_mode,
221 static bool mep_vector_mode_supported_p (enum machine_mode);
222 static bool mep_handle_option (size_t, const char *, int);
223 static rtx mep_allocate_initial_value (rtx);
224 static void mep_asm_init_sections (void);
225 static int mep_comp_type_attributes (const_tree, const_tree);
226 static bool mep_narrow_volatile_bitfield (void);
227 static rtx mep_expand_builtin_saveregs (void);
228 static tree mep_build_builtin_va_list (void);
229 static void mep_expand_va_start (tree, rtx);
230 static tree mep_gimplify_va_arg_expr (tree, tree, tree *, tree *);
231 static bool mep_can_eliminate (const int, const int);
232 static void mep_trampoline_init (rtx, tree, rtx);
234 /* Initialize the GCC target structure. */
236 #undef TARGET_ASM_FUNCTION_PROLOGUE
237 #define TARGET_ASM_FUNCTION_PROLOGUE mep_start_function
238 #undef TARGET_ATTRIBUTE_TABLE
239 #define TARGET_ATTRIBUTE_TABLE mep_attribute_table
240 #undef TARGET_COMP_TYPE_ATTRIBUTES
241 #define TARGET_COMP_TYPE_ATTRIBUTES mep_comp_type_attributes
242 #undef TARGET_INSERT_ATTRIBUTES
243 #define TARGET_INSERT_ATTRIBUTES mep_insert_attributes
244 #undef TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P
245 #define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P mep_function_attribute_inlinable_p
246 #undef TARGET_CAN_INLINE_P
247 #define TARGET_CAN_INLINE_P mep_can_inline_p
248 #undef TARGET_SECTION_TYPE_FLAGS
249 #define TARGET_SECTION_TYPE_FLAGS mep_section_type_flags
250 #undef TARGET_ASM_NAMED_SECTION
251 #define TARGET_ASM_NAMED_SECTION mep_asm_named_section
252 #undef TARGET_INIT_BUILTINS
253 #define TARGET_INIT_BUILTINS mep_init_builtins
254 #undef TARGET_EXPAND_BUILTIN
255 #define TARGET_EXPAND_BUILTIN mep_expand_builtin
256 #undef TARGET_SCHED_ADJUST_COST
257 #define TARGET_SCHED_ADJUST_COST mep_adjust_cost
258 #undef TARGET_SCHED_ISSUE_RATE
259 #define TARGET_SCHED_ISSUE_RATE mep_issue_rate
260 #undef TARGET_SCHED_REORDER
261 #define TARGET_SCHED_REORDER mep_sched_reorder
262 #undef TARGET_STRIP_NAME_ENCODING
263 #define TARGET_STRIP_NAME_ENCODING mep_strip_name_encoding
264 #undef TARGET_ASM_SELECT_SECTION
265 #define TARGET_ASM_SELECT_SECTION mep_select_section
266 #undef TARGET_ASM_UNIQUE_SECTION
267 #define TARGET_ASM_UNIQUE_SECTION mep_unique_section
268 #undef TARGET_ENCODE_SECTION_INFO
269 #define TARGET_ENCODE_SECTION_INFO mep_encode_section_info
270 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
271 #define TARGET_FUNCTION_OK_FOR_SIBCALL mep_function_ok_for_sibcall
272 #undef TARGET_RTX_COSTS
273 #define TARGET_RTX_COSTS mep_rtx_cost
274 #undef TARGET_ADDRESS_COST
275 #define TARGET_ADDRESS_COST mep_address_cost
276 #undef TARGET_MACHINE_DEPENDENT_REORG
277 #define TARGET_MACHINE_DEPENDENT_REORG mep_reorg
278 #undef TARGET_SETUP_INCOMING_VARARGS
279 #define TARGET_SETUP_INCOMING_VARARGS mep_setup_incoming_varargs
280 #undef TARGET_PASS_BY_REFERENCE
281 #define TARGET_PASS_BY_REFERENCE mep_pass_by_reference
282 #undef TARGET_VECTOR_MODE_SUPPORTED_P
283 #define TARGET_VECTOR_MODE_SUPPORTED_P mep_vector_mode_supported_p
284 #undef TARGET_HANDLE_OPTION
285 #define TARGET_HANDLE_OPTION mep_handle_option
286 #undef TARGET_DEFAULT_TARGET_FLAGS
287 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
288 #undef TARGET_ALLOCATE_INITIAL_VALUE
289 #define TARGET_ALLOCATE_INITIAL_VALUE mep_allocate_initial_value
290 #undef TARGET_ASM_INIT_SECTIONS
291 #define TARGET_ASM_INIT_SECTIONS mep_asm_init_sections
292 #undef TARGET_RETURN_IN_MEMORY
293 #define TARGET_RETURN_IN_MEMORY mep_return_in_memory
294 #undef TARGET_NARROW_VOLATILE_BITFIELD
295 #define TARGET_NARROW_VOLATILE_BITFIELD mep_narrow_volatile_bitfield
296 #undef TARGET_EXPAND_BUILTIN_SAVEREGS
297 #define TARGET_EXPAND_BUILTIN_SAVEREGS mep_expand_builtin_saveregs
298 #undef TARGET_BUILD_BUILTIN_VA_LIST
299 #define TARGET_BUILD_BUILTIN_VA_LIST mep_build_builtin_va_list
300 #undef TARGET_EXPAND_BUILTIN_VA_START
301 #define TARGET_EXPAND_BUILTIN_VA_START mep_expand_va_start
302 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
303 #define TARGET_GIMPLIFY_VA_ARG_EXPR mep_gimplify_va_arg_expr
304 #undef TARGET_CAN_ELIMINATE
305 #define TARGET_CAN_ELIMINATE mep_can_eliminate
306 #undef TARGET_TRAMPOLINE_INIT
307 #define TARGET_TRAMPOLINE_INIT mep_trampoline_init
309 struct gcc_target targetm = TARGET_INITIALIZER;
311 #define WANT_GCC_DEFINITIONS
312 #include "mep-intrin.h"
313 #undef WANT_GCC_DEFINITIONS
316 /* Command Line Option Support. */
318 char mep_leaf_registers [FIRST_PSEUDO_REGISTER];
320 /* True if we can use cmov instructions to move values back and forth
321 between core and coprocessor registers. */
322 bool mep_have_core_copro_moves_p;
324 /* True if we can use cmov instructions (or a work-alike) to move
325 values between coprocessor registers. */
326 bool mep_have_copro_copro_moves_p;
328 /* A table of all coprocessor instructions that can act like
329 a coprocessor-to-coprocessor cmov. */
330 static const int mep_cmov_insns[] = {
343 static int option_mtiny_specified = 0;
347 mep_set_leaf_registers (int enable)
351 if (mep_leaf_registers[0] != enable)
352 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
353 mep_leaf_registers[i] = enable;
357 mep_conditional_register_usage (char *fixed_regs, char *call_used_regs)
361 if (!TARGET_OPT_MULT && !TARGET_OPT_DIV)
363 fixed_regs[HI_REGNO] = 1;
364 fixed_regs[LO_REGNO] = 1;
365 call_used_regs[HI_REGNO] = 1;
366 call_used_regs[LO_REGNO] = 1;
369 for (i = FIRST_SHADOW_REGISTER; i <= LAST_SHADOW_REGISTER; i++)
374 mep_optimization_options (void)
376 /* The first scheduling pass often increases register pressure and tends
377 to result in more spill code. Only run it when specifically asked. */
378 flag_schedule_insns = 0;
380 /* Using $fp doesn't gain us much, even when debugging is important. */
381 flag_omit_frame_pointer = 1;
385 mep_override_options (void)
388 warning (OPT_fpic, "-fpic is not supported");
390 warning (OPT_fPIC, "-fPIC is not supported");
391 if (TARGET_S && TARGET_M)
392 error ("only one of -ms and -mm may be given");
393 if (TARGET_S && TARGET_L)
394 error ("only one of -ms and -ml may be given");
395 if (TARGET_M && TARGET_L)
396 error ("only one of -mm and -ml may be given");
397 if (TARGET_S && option_mtiny_specified)
398 error ("only one of -ms and -mtiny= may be given");
399 if (TARGET_M && option_mtiny_specified)
400 error ("only one of -mm and -mtiny= may be given");
401 if (TARGET_OPT_CLIP && ! TARGET_OPT_MINMAX)
402 warning (0, "-mclip currently has no effect without -mminmax");
404 if (mep_const_section)
406 if (strcmp (mep_const_section, "tiny") != 0
407 && strcmp (mep_const_section, "near") != 0
408 && strcmp (mep_const_section, "far") != 0)
409 error ("-mc= must be -mc=tiny, -mc=near, or -mc=far");
413 mep_tiny_cutoff = 65536;
416 if (TARGET_L && ! option_mtiny_specified)
419 if (TARGET_64BIT_CR_REGS)
420 flag_split_wide_types = 0;
422 init_machine_status = mep_init_machine_status;
423 mep_init_intrinsics ();
426 /* Pattern Support - constraints, predicates, expanders. */
428 /* MEP has very few instructions that can refer to the span of
429 addresses used by symbols, so it's common to check for them. */
434 int c = GET_CODE (x);
436 return (c == CONST_INT
446 if (GET_CODE (x) != MEM)
449 c = GET_CODE (XEXP (x, 0));
450 return (c == CONST_INT
455 /* static const char *reg_class_names[] = REG_CLASS_NAMES; */
457 #define GEN_REG(R, STRICT) \
460 && ((R) == ARG_POINTER_REGNUM \
461 || (R) >= FIRST_PSEUDO_REGISTER)))
463 static char pattern[12], *patternp;
464 static GTY(()) rtx patternr[12];
465 #define RTX_IS(x) (strcmp (pattern, x) == 0)
468 encode_pattern_1 (rtx x)
472 if (patternp == pattern + sizeof (pattern) - 2)
478 patternr[patternp-pattern] = x;
480 switch (GET_CODE (x))
488 encode_pattern_1 (XEXP(x, 0));
492 encode_pattern_1 (XEXP(x, 0));
493 encode_pattern_1 (XEXP(x, 1));
497 encode_pattern_1 (XEXP(x, 0));
498 encode_pattern_1 (XEXP(x, 1));
502 encode_pattern_1 (XEXP(x, 0));
516 *patternp++ = '0' + XCINT(x, 1, UNSPEC);
517 for (i=0; i<XVECLEN (x, 0); i++)
518 encode_pattern_1 (XVECEXP (x, 0, i));
526 fprintf (stderr, "can't encode pattern %s\n", GET_RTX_NAME(GET_CODE(x)));
535 encode_pattern (rtx x)
538 encode_pattern_1 (x);
543 mep_section_tag (rtx x)
549 switch (GET_CODE (x))
556 x = XVECEXP (x, 0, 0);
559 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
568 if (GET_CODE (x) != SYMBOL_REF)
571 if (name[0] == '@' && name[2] == '.')
573 if (name[1] == 'i' || name[1] == 'I')
576 return 'f'; /* near */
577 return 'n'; /* far */
585 mep_regno_reg_class (int regno)
589 case SP_REGNO: return SP_REGS;
590 case TP_REGNO: return TP_REGS;
591 case GP_REGNO: return GP_REGS;
592 case 0: return R0_REGS;
593 case HI_REGNO: return HI_REGS;
594 case LO_REGNO: return LO_REGS;
595 case ARG_POINTER_REGNUM: return GENERAL_REGS;
598 if (GR_REGNO_P (regno))
599 return regno < FIRST_GR_REGNO + 8 ? TPREL_REGS : GENERAL_REGS;
600 if (CONTROL_REGNO_P (regno))
603 if (CR_REGNO_P (regno))
607 /* Search for the register amongst user-defined subclasses of
608 the coprocessor registers. */
609 for (i = USER0_REGS; i <= USER3_REGS; ++i)
611 if (! TEST_HARD_REG_BIT (reg_class_contents[i], regno))
613 for (j = 0; j < N_REG_CLASSES; ++j)
615 enum reg_class sub = reg_class_subclasses[i][j];
617 if (sub == LIM_REG_CLASSES)
619 if (TEST_HARD_REG_BIT (reg_class_contents[sub], regno))
624 return LOADABLE_CR_REGNO_P (regno) ? LOADABLE_CR_REGS : CR_REGS;
627 if (CCR_REGNO_P (regno))
630 gcc_assert (regno >= FIRST_SHADOW_REGISTER && regno <= LAST_SHADOW_REGISTER);
636 mep_reg_class_from_constraint (int c, const char *str)
653 return LOADABLE_CR_REGS;
655 return mep_have_copro_copro_moves_p ? CR_REGS : NO_REGS;
657 return mep_have_core_copro_moves_p ? CR_REGS : NO_REGS;
684 enum reg_class which = c - 'A' + USER0_REGS;
685 return (reg_class_size[which] > 0 ? which : NO_REGS);
694 mep_const_ok_for_letter_p (HOST_WIDE_INT value, int c)
698 case 'I': return value >= -32768 && value < 32768;
699 case 'J': return value >= 0 && value < 65536;
700 case 'K': return value >= 0 && value < 0x01000000;
701 case 'L': return value >= -32 && value < 32;
702 case 'M': return value >= 0 && value < 32;
703 case 'N': return value >= 0 && value < 16;
707 return value >= -2147483647-1 && value <= 2147483647;
714 mep_extra_constraint (rtx value, int c)
716 encode_pattern (value);
721 /* For near symbols, like what call uses. */
722 if (GET_CODE (value) == REG)
724 return mep_call_address_operand (value, GET_MODE (value));
727 /* For signed 8-bit immediates. */
728 return (GET_CODE (value) == CONST_INT
729 && INTVAL (value) >= -128
730 && INTVAL (value) <= 127);
733 /* For tp/gp relative symbol values. */
734 return (RTX_IS ("u3s") || RTX_IS ("u2s")
735 || RTX_IS ("+u3si") || RTX_IS ("+u2si"));
738 /* Non-absolute memories. */
739 return GET_CODE (value) == MEM && ! CONSTANT_P (XEXP (value, 0));
743 return RTX_IS ("Hs");
746 /* Register indirect. */
747 return RTX_IS ("mr");
750 return mep_section_tag (value) == 'c' && RTX_IS ("ms");
761 const_in_range (rtx x, int minv, int maxv)
763 return (GET_CODE (x) == CONST_INT
764 && INTVAL (x) >= minv
765 && INTVAL (x) <= maxv);
768 /* Given three integer registers DEST, SRC1 and SRC2, return an rtx X
769 such that "mulr DEST,X" will calculate DEST = SRC1 * SRC2. If a move
770 is needed, emit it before INSN if INSN is nonnull, otherwise emit it
771 at the end of the insn stream. */
774 mep_mulr_source (rtx insn, rtx dest, rtx src1, rtx src2)
776 if (rtx_equal_p (dest, src1))
778 else if (rtx_equal_p (dest, src2))
783 emit_insn (gen_movsi (copy_rtx (dest), src1));
785 emit_insn_before (gen_movsi (copy_rtx (dest), src1), insn);
790 /* Replace INSN's pattern with PATTERN, a multiplication PARALLEL.
791 Change the last element of PATTERN from (clobber (scratch:SI))
792 to (clobber (reg:SI HI_REGNO)). */
795 mep_rewrite_mult (rtx insn, rtx pattern)
799 hi_clobber = XVECEXP (pattern, 0, XVECLEN (pattern, 0) - 1);
800 XEXP (hi_clobber, 0) = gen_rtx_REG (SImode, HI_REGNO);
801 PATTERN (insn) = pattern;
802 INSN_CODE (insn) = -1;
805 /* Subroutine of mep_reuse_lo_p. Rewrite instruction INSN so that it
806 calculates SRC1 * SRC2 and stores the result in $lo. Also make it
807 store the result in DEST if nonnull. */
810 mep_rewrite_mulsi3 (rtx insn, rtx dest, rtx src1, rtx src2)
814 lo = gen_rtx_REG (SImode, LO_REGNO);
816 pattern = gen_mulsi3r (lo, dest, copy_rtx (dest),
817 mep_mulr_source (insn, dest, src1, src2));
819 pattern = gen_mulsi3_lo (lo, src1, src2);
820 mep_rewrite_mult (insn, pattern);
823 /* Like mep_rewrite_mulsi3, but calculate SRC1 * SRC2 + SRC3. First copy
824 SRC3 into $lo, then use either madd or maddr. The move into $lo will
825 be deleted by a peephole2 if SRC3 is already in $lo. */
828 mep_rewrite_maddsi3 (rtx insn, rtx dest, rtx src1, rtx src2, rtx src3)
832 lo = gen_rtx_REG (SImode, LO_REGNO);
833 emit_insn_before (gen_movsi (copy_rtx (lo), src3), insn);
835 pattern = gen_maddsi3r (lo, dest, copy_rtx (dest),
836 mep_mulr_source (insn, dest, src1, src2),
839 pattern = gen_maddsi3_lo (lo, src1, src2, copy_rtx (lo));
840 mep_rewrite_mult (insn, pattern);
843 /* Return true if $lo has the same value as integer register GPR when
844 instruction INSN is reached. If necessary, rewrite the instruction
845 that sets $lo so that it uses a proper SET, not a CLOBBER. LO is an
846 rtx for (reg:SI LO_REGNO).
848 This function is intended to be used by the peephole2 pass. Since
849 that pass goes from the end of a basic block to the beginning, and
850 propagates liveness information on the way, there is no need to
851 update register notes here.
853 If GPR_DEAD_P is true on entry, and this function returns true,
854 then the caller will replace _every_ use of GPR in and after INSN
855 with LO. This means that if the instruction that sets $lo is a
856 mulr- or maddr-type instruction, we can rewrite it to use mul or
857 madd instead. In combination with the copy progagation pass,
858 this allows us to replace sequences like:
867 if GPR is no longer used. */
870 mep_reuse_lo_p_1 (rtx lo, rtx gpr, rtx insn, bool gpr_dead_p)
874 insn = PREV_INSN (insn);
876 switch (recog_memoized (insn))
878 case CODE_FOR_mulsi3_1:
880 if (rtx_equal_p (recog_data.operand[0], gpr))
882 mep_rewrite_mulsi3 (insn,
883 gpr_dead_p ? NULL : recog_data.operand[0],
884 recog_data.operand[1],
885 recog_data.operand[2]);
890 case CODE_FOR_maddsi3:
892 if (rtx_equal_p (recog_data.operand[0], gpr))
894 mep_rewrite_maddsi3 (insn,
895 gpr_dead_p ? NULL : recog_data.operand[0],
896 recog_data.operand[1],
897 recog_data.operand[2],
898 recog_data.operand[3]);
903 case CODE_FOR_mulsi3r:
904 case CODE_FOR_maddsi3r:
906 return rtx_equal_p (recog_data.operand[1], gpr);
909 if (reg_set_p (lo, insn)
910 || reg_set_p (gpr, insn)
911 || volatile_insn_p (PATTERN (insn)))
914 if (gpr_dead_p && reg_referenced_p (gpr, PATTERN (insn)))
919 while (!NOTE_INSN_BASIC_BLOCK_P (insn));
923 /* A wrapper around mep_reuse_lo_p_1 that preserves recog_data. */
926 mep_reuse_lo_p (rtx lo, rtx gpr, rtx insn, bool gpr_dead_p)
928 bool result = mep_reuse_lo_p_1 (lo, gpr, insn, gpr_dead_p);
933 /* Return true if SET can be turned into a post-modify load or store
934 that adds OFFSET to GPR. In other words, return true if SET can be
937 (parallel [SET (set GPR (plus:SI GPR OFFSET))]).
939 It's OK to change SET to an equivalent operation in order to
943 mep_use_post_modify_for_set_p (rtx set, rtx gpr, rtx offset)
946 unsigned int reg_bytes, mem_bytes;
947 enum machine_mode reg_mode, mem_mode;
949 /* Only simple SETs can be converted. */
950 if (GET_CODE (set) != SET)
953 /* Point REG to what we hope will be the register side of the set and
954 MEM to what we hope will be the memory side. */
955 if (GET_CODE (SET_DEST (set)) == MEM)
957 mem = &SET_DEST (set);
958 reg = &SET_SRC (set);
962 reg = &SET_DEST (set);
963 mem = &SET_SRC (set);
964 if (GET_CODE (*mem) == SIGN_EXTEND)
965 mem = &XEXP (*mem, 0);
968 /* Check that *REG is a suitable coprocessor register. */
969 if (GET_CODE (*reg) != REG || !LOADABLE_CR_REGNO_P (REGNO (*reg)))
972 /* Check that *MEM is a suitable memory reference. */
973 if (GET_CODE (*mem) != MEM || !rtx_equal_p (XEXP (*mem, 0), gpr))
976 /* Get the number of bytes in each operand. */
977 mem_bytes = GET_MODE_SIZE (GET_MODE (*mem));
978 reg_bytes = GET_MODE_SIZE (GET_MODE (*reg));
980 /* Check that OFFSET is suitably aligned. */
981 if (INTVAL (offset) & (mem_bytes - 1))
984 /* Convert *MEM to a normal integer mode. */
985 mem_mode = mode_for_size (mem_bytes * BITS_PER_UNIT, MODE_INT, 0);
986 *mem = change_address (*mem, mem_mode, NULL);
988 /* Adjust *REG as well. */
989 *reg = shallow_copy_rtx (*reg);
990 if (reg == &SET_DEST (set) && reg_bytes < UNITS_PER_WORD)
992 /* SET is a subword load. Convert it to an explicit extension. */
993 PUT_MODE (*reg, SImode);
994 *mem = gen_rtx_SIGN_EXTEND (SImode, *mem);
998 reg_mode = mode_for_size (reg_bytes * BITS_PER_UNIT, MODE_INT, 0);
999 PUT_MODE (*reg, reg_mode);
1004 /* Return the effect of frame-related instruction INSN. */
1007 mep_frame_expr (rtx insn)
1011 note = find_reg_note (insn, REG_FRAME_RELATED_EXPR, 0);
1012 expr = (note != 0 ? XEXP (note, 0) : copy_rtx (PATTERN (insn)));
1013 RTX_FRAME_RELATED_P (expr) = 1;
1017 /* Merge instructions INSN1 and INSN2 using a PARALLEL. Store the
1018 new pattern in INSN1; INSN2 will be deleted by the caller. */
1021 mep_make_parallel (rtx insn1, rtx insn2)
1025 if (RTX_FRAME_RELATED_P (insn2))
1027 expr = mep_frame_expr (insn2);
1028 if (RTX_FRAME_RELATED_P (insn1))
1029 expr = gen_rtx_SEQUENCE (VOIDmode,
1030 gen_rtvec (2, mep_frame_expr (insn1), expr));
1031 set_unique_reg_note (insn1, REG_FRAME_RELATED_EXPR, expr);
1032 RTX_FRAME_RELATED_P (insn1) = 1;
1035 PATTERN (insn1) = gen_rtx_PARALLEL (VOIDmode,
1036 gen_rtvec (2, PATTERN (insn1),
1038 INSN_CODE (insn1) = -1;
1041 /* SET_INSN is an instruction that adds OFFSET to REG. Go back through
1042 the basic block to see if any previous load or store instruction can
1043 be persuaded to do SET_INSN as a side-effect. Return true if so. */
1046 mep_use_post_modify_p_1 (rtx set_insn, rtx reg, rtx offset)
1053 insn = PREV_INSN (insn);
1056 if (mep_use_post_modify_for_set_p (PATTERN (insn), reg, offset))
1058 mep_make_parallel (insn, set_insn);
1062 if (reg_set_p (reg, insn)
1063 || reg_referenced_p (reg, PATTERN (insn))
1064 || volatile_insn_p (PATTERN (insn)))
1068 while (!NOTE_INSN_BASIC_BLOCK_P (insn));
1072 /* A wrapper around mep_use_post_modify_p_1 that preserves recog_data. */
1075 mep_use_post_modify_p (rtx insn, rtx reg, rtx offset)
1077 bool result = mep_use_post_modify_p_1 (insn, reg, offset);
1078 extract_insn (insn);
1083 mep_allow_clip (rtx ux, rtx lx, int s)
1085 HOST_WIDE_INT u = INTVAL (ux);
1086 HOST_WIDE_INT l = INTVAL (lx);
1089 if (!TARGET_OPT_CLIP)
1094 for (i = 0; i < 30; i ++)
1095 if ((u == ((HOST_WIDE_INT) 1 << i) - 1)
1096 && (l == - ((HOST_WIDE_INT) 1 << i)))
1104 for (i = 0; i < 30; i ++)
1105 if ((u == ((HOST_WIDE_INT) 1 << i) - 1))
1112 mep_bit_position_p (rtx x, bool looking_for)
1114 if (GET_CODE (x) != CONST_INT)
1116 switch ((int) INTVAL(x) & 0xff)
1118 case 0x01: case 0x02: case 0x04: case 0x08:
1119 case 0x10: case 0x20: case 0x40: case 0x80:
1121 case 0xfe: case 0xfd: case 0xfb: case 0xf7:
1122 case 0xef: case 0xdf: case 0xbf: case 0x7f:
1123 return !looking_for;
1129 move_needs_splitting (rtx dest, rtx src,
1130 enum machine_mode mode ATTRIBUTE_UNUSED)
1132 int s = mep_section_tag (src);
1136 if (GET_CODE (src) == CONST
1137 || GET_CODE (src) == MEM)
1138 src = XEXP (src, 0);
1139 else if (GET_CODE (src) == SYMBOL_REF
1140 || GET_CODE (src) == LABEL_REF
1141 || GET_CODE (src) == PLUS)
1147 || (GET_CODE (src) == PLUS
1148 && GET_CODE (XEXP (src, 1)) == CONST_INT
1149 && (INTVAL (XEXP (src, 1)) < -65536
1150 || INTVAL (XEXP (src, 1)) > 0xffffff))
1151 || (GET_CODE (dest) == REG
1152 && REGNO (dest) > 7 && REGNO (dest) < FIRST_PSEUDO_REGISTER))
1158 mep_split_mov (rtx *operands, int symbolic)
1162 if (move_needs_splitting (operands[0], operands[1], SImode))
1167 if (GET_CODE (operands[1]) != CONST_INT)
1170 if (constraint_satisfied_p (operands[1], CONSTRAINT_I)
1171 || constraint_satisfied_p (operands[1], CONSTRAINT_J)
1172 || constraint_satisfied_p (operands[1], CONSTRAINT_O))
1175 if (((!reload_completed && !reload_in_progress)
1176 || (REG_P (operands[0]) && REGNO (operands[0]) < 8))
1177 && constraint_satisfied_p (operands[1], CONSTRAINT_K))
1183 /* Irritatingly, the "jsrv" insn *toggles* PSW.OM rather than set
1184 it to one specific value. So the insn chosen depends on whether
1185 the source and destination modes match. */
1188 mep_vliw_mode_match (rtx tgt)
1190 bool src_vliw = mep_vliw_function_p (cfun->decl);
1191 bool tgt_vliw = INTVAL (tgt);
1193 return src_vliw == tgt_vliw;
1196 /* Like the above, but also test for near/far mismatches. */
1199 mep_vliw_jmp_match (rtx tgt)
1201 bool src_vliw = mep_vliw_function_p (cfun->decl);
1202 bool tgt_vliw = INTVAL (tgt);
1204 if (mep_section_tag (DECL_RTL (cfun->decl)) == 'f')
1207 return src_vliw == tgt_vliw;
1211 mep_multi_slot (rtx x)
1213 return get_attr_slot (x) == SLOT_MULTI;
1218 mep_legitimate_constant_p (rtx x)
1220 /* We can't convert symbol values to gp- or tp-rel values after
1221 reload, as reload might have used $gp or $tp for other
1223 if (GET_CODE (x) == SYMBOL_REF && (reload_in_progress || reload_completed))
1225 char e = mep_section_tag (x);
1226 return (e != 't' && e != 'b');
1231 /* Be careful not to use macros that need to be compiled one way for
1232 strict, and another way for not-strict, like REG_OK_FOR_BASE_P. */
1235 mep_legitimate_address (enum machine_mode mode, rtx x, int strict)
1239 #define DEBUG_LEGIT 0
1241 fprintf (stderr, "legit: mode %s strict %d ", mode_name[mode], strict);
1245 if (GET_CODE (x) == LO_SUM
1246 && GET_CODE (XEXP (x, 0)) == REG
1247 && GEN_REG (REGNO (XEXP (x, 0)), strict)
1248 && CONSTANT_P (XEXP (x, 1)))
1250 if (GET_MODE_SIZE (mode) > 4)
1252 /* We will end up splitting this, and lo_sums are not
1253 offsettable for us. */
1255 fprintf(stderr, " - nope, %%lo(sym)[reg] not splittable\n");
1260 fprintf (stderr, " - yup, %%lo(sym)[reg]\n");
1265 if (GET_CODE (x) == REG
1266 && GEN_REG (REGNO (x), strict))
1269 fprintf (stderr, " - yup, [reg]\n");
1274 if (GET_CODE (x) == PLUS
1275 && GET_CODE (XEXP (x, 0)) == REG
1276 && GEN_REG (REGNO (XEXP (x, 0)), strict)
1277 && const_in_range (XEXP (x, 1), -32768, 32767))
1280 fprintf (stderr, " - yup, [reg+const]\n");
1285 if (GET_CODE (x) == PLUS
1286 && GET_CODE (XEXP (x, 0)) == REG
1287 && GEN_REG (REGNO (XEXP (x, 0)), strict)
1288 && GET_CODE (XEXP (x, 1)) == CONST
1289 && (GET_CODE (XEXP (XEXP (x, 1), 0)) == UNSPEC
1290 || (GET_CODE (XEXP (XEXP (x, 1), 0)) == PLUS
1291 && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 0)) == UNSPEC
1292 && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 1)) == CONST_INT)))
1295 fprintf (stderr, " - yup, [reg+unspec]\n");
1300 the_tag = mep_section_tag (x);
1305 fprintf (stderr, " - nope, [far]\n");
1310 if (mode == VOIDmode
1311 && GET_CODE (x) == SYMBOL_REF)
1314 fprintf (stderr, " - yup, call [symbol]\n");
1319 if ((mode == SImode || mode == SFmode)
1321 && LEGITIMATE_CONSTANT_P (x)
1322 && the_tag != 't' && the_tag != 'b')
1324 if (GET_CODE (x) != CONST_INT
1325 || (INTVAL (x) <= 0xfffff
1327 && (INTVAL (x) % 4) == 0))
1330 fprintf (stderr, " - yup, [const]\n");
1337 fprintf (stderr, " - nope.\n");
1343 mep_legitimize_reload_address (rtx *x, enum machine_mode mode, int opnum,
1344 enum reload_type type,
1345 int ind_levels ATTRIBUTE_UNUSED)
1347 if (GET_CODE (*x) == PLUS
1348 && GET_CODE (XEXP (*x, 0)) == MEM
1349 && GET_CODE (XEXP (*x, 1)) == REG)
1351 /* GCC will by default copy the MEM into a REG, which results in
1352 an invalid address. For us, the best thing to do is move the
1353 whole expression to a REG. */
1354 push_reload (*x, NULL_RTX, x, NULL,
1355 GENERAL_REGS, mode, VOIDmode,
1360 if (GET_CODE (*x) == PLUS
1361 && GET_CODE (XEXP (*x, 0)) == SYMBOL_REF
1362 && GET_CODE (XEXP (*x, 1)) == CONST_INT)
1364 char e = mep_section_tag (XEXP (*x, 0));
1366 if (e != 't' && e != 'b')
1368 /* GCC thinks that (sym+const) is a valid address. Well,
1369 sometimes it is, this time it isn't. The best thing to
1370 do is reload the symbol to a register, since reg+int
1371 tends to work, and we can't just add the symbol and
1373 push_reload (XEXP (*x, 0), NULL_RTX, &(XEXP(*x, 0)), NULL,
1374 GENERAL_REGS, mode, VOIDmode,
1383 mep_core_address_length (rtx insn, int opn)
1385 rtx set = single_set (insn);
1386 rtx mem = XEXP (set, opn);
1387 rtx other = XEXP (set, 1-opn);
1388 rtx addr = XEXP (mem, 0);
1390 if (register_operand (addr, Pmode))
1392 if (GET_CODE (addr) == PLUS)
1394 rtx addend = XEXP (addr, 1);
1396 gcc_assert (REG_P (XEXP (addr, 0)));
1398 switch (REGNO (XEXP (addr, 0)))
1400 case STACK_POINTER_REGNUM:
1401 if (GET_MODE_SIZE (GET_MODE (mem)) == 4
1402 && mep_imm7a4_operand (addend, VOIDmode))
1407 gcc_assert (REG_P (other));
1409 if (REGNO (other) >= 8)
1412 if (GET_CODE (addend) == CONST
1413 && GET_CODE (XEXP (addend, 0)) == UNSPEC
1414 && XINT (XEXP (addend, 0), 1) == UNS_TPREL)
1417 if (GET_CODE (addend) == CONST_INT
1418 && INTVAL (addend) >= 0
1419 && INTVAL (addend) <= 127
1420 && INTVAL (addend) % GET_MODE_SIZE (GET_MODE (mem)) == 0)
1430 mep_cop_address_length (rtx insn, int opn)
1432 rtx set = single_set (insn);
1433 rtx mem = XEXP (set, opn);
1434 rtx addr = XEXP (mem, 0);
1436 if (GET_CODE (mem) != MEM)
1438 if (register_operand (addr, Pmode))
1440 if (GET_CODE (addr) == POST_INC)
1446 #define DEBUG_EXPAND_MOV 0
1448 mep_expand_mov (rtx *operands, enum machine_mode mode)
1453 int post_reload = 0;
1455 tag[0] = mep_section_tag (operands[0]);
1456 tag[1] = mep_section_tag (operands[1]);
1458 if (!reload_in_progress
1459 && !reload_completed
1460 && GET_CODE (operands[0]) != REG
1461 && GET_CODE (operands[0]) != SUBREG
1462 && GET_CODE (operands[1]) != REG
1463 && GET_CODE (operands[1]) != SUBREG)
1464 operands[1] = copy_to_mode_reg (mode, operands[1]);
1466 #if DEBUG_EXPAND_MOV
1467 fprintf(stderr, "expand move %s %d\n", mode_name[mode],
1468 reload_in_progress || reload_completed);
1469 debug_rtx (operands[0]);
1470 debug_rtx (operands[1]);
1473 if (mode == DImode || mode == DFmode)
1476 if (reload_in_progress || reload_completed)
1480 if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == TP_REGNO)
1481 cfun->machine->reload_changes_tp = true;
1483 if (tag[0] == 't' || tag[1] == 't')
1485 r = has_hard_reg_initial_val (Pmode, GP_REGNO);
1486 if (!r || GET_CODE (r) != REG || REGNO (r) != GP_REGNO)
1489 if (tag[0] == 'b' || tag[1] == 'b')
1491 r = has_hard_reg_initial_val (Pmode, TP_REGNO);
1492 if (!r || GET_CODE (r) != REG || REGNO (r) != TP_REGNO)
1495 if (cfun->machine->reload_changes_tp == true)
1502 if (symbol_p (operands[1]))
1504 t = mep_section_tag (operands[1]);
1505 if (t == 'b' || t == 't')
1508 if (GET_CODE (operands[1]) == SYMBOL_REF)
1510 tpsym = operands[1];
1511 n = gen_rtx_UNSPEC (mode,
1512 gen_rtvec (1, operands[1]),
1513 t == 'b' ? UNS_TPREL : UNS_GPREL);
1514 n = gen_rtx_CONST (mode, n);
1516 else if (GET_CODE (operands[1]) == CONST
1517 && GET_CODE (XEXP (operands[1], 0)) == PLUS
1518 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF
1519 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT)
1521 tpsym = XEXP (XEXP (operands[1], 0), 0);
1522 tpoffs = XEXP (XEXP (operands[1], 0), 1);
1523 n = gen_rtx_UNSPEC (mode,
1524 gen_rtvec (1, tpsym),
1525 t == 'b' ? UNS_TPREL : UNS_GPREL);
1526 n = gen_rtx_PLUS (mode, n, tpoffs);
1527 n = gen_rtx_CONST (mode, n);
1529 else if (GET_CODE (operands[1]) == CONST
1530 && GET_CODE (XEXP (operands[1], 0)) == UNSPEC)
1534 error ("unusual TP-relative address");
1538 n = gen_rtx_PLUS (mode, (t == 'b' ? mep_tp_rtx ()
1539 : mep_gp_rtx ()), n);
1540 n = emit_insn (gen_rtx_SET (mode, operands[0], n));
1541 #if DEBUG_EXPAND_MOV
1542 fprintf(stderr, "mep_expand_mov emitting ");
1549 for (i=0; i < 2; i++)
1551 t = mep_section_tag (operands[i]);
1552 if (GET_CODE (operands[i]) == MEM && (t == 'b' || t == 't'))
1557 sym = XEXP (operands[i], 0);
1558 if (GET_CODE (sym) == CONST
1559 && GET_CODE (XEXP (sym, 0)) == UNSPEC)
1560 sym = XVECEXP (XEXP (sym, 0), 0, 0);
1573 n = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), u);
1574 n = gen_rtx_CONST (Pmode, n);
1575 n = gen_rtx_PLUS (Pmode, r, n);
1576 operands[i] = replace_equiv_address (operands[i], n);
1581 if ((GET_CODE (operands[1]) != REG
1582 && MEP_CONTROL_REG (operands[0]))
1583 || (GET_CODE (operands[0]) != REG
1584 && MEP_CONTROL_REG (operands[1])))
1587 #if DEBUG_EXPAND_MOV
1588 fprintf (stderr, "cr-mem, forcing op1 to reg\n");
1590 temp = gen_reg_rtx (mode);
1591 emit_move_insn (temp, operands[1]);
1595 if (symbolref_p (operands[0])
1596 && (mep_section_tag (XEXP (operands[0], 0)) == 'f'
1597 || (GET_MODE_SIZE (mode) != 4)))
1601 gcc_assert (!reload_in_progress && !reload_completed);
1603 temp = force_reg (Pmode, XEXP (operands[0], 0));
1604 operands[0] = replace_equiv_address (operands[0], temp);
1605 emit_move_insn (operands[0], operands[1]);
1609 if (!post_reload && (tag[1] == 't' || tag[1] == 'b'))
1612 if (symbol_p (operands[1])
1613 && (tag[1] == 'f' || tag[1] == 't' || tag[1] == 'b'))
1615 emit_insn (gen_movsi_topsym_s (operands[0], operands[1]));
1616 emit_insn (gen_movsi_botsym_s (operands[0], operands[0], operands[1]));
1620 if (symbolref_p (operands[1])
1621 && (tag[1] == 'f' || tag[1] == 't' || tag[1] == 'b'))
1625 if (reload_in_progress || reload_completed)
1628 temp = gen_reg_rtx (Pmode);
1630 emit_insn (gen_movsi_topsym_s (temp, operands[1]));
1631 emit_insn (gen_movsi_botsym_s (temp, temp, operands[1]));
1632 emit_move_insn (operands[0], replace_equiv_address (operands[1], temp));
1639 /* Cases where the pattern can't be made to use at all. */
1642 mep_mov_ok (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
1646 #define DEBUG_MOV_OK 0
1648 fprintf (stderr, "mep_mov_ok %s %c=%c\n", mode_name[mode], mep_section_tag (operands[0]),
1649 mep_section_tag (operands[1]));
1650 debug_rtx (operands[0]);
1651 debug_rtx (operands[1]);
1654 /* We want the movh patterns to get these. */
1655 if (GET_CODE (operands[1]) == HIGH)
1658 /* We can't store a register to a far variable without using a
1659 scratch register to hold the address. Using far variables should
1660 be split by mep_emit_mov anyway. */
1661 if (mep_section_tag (operands[0]) == 'f'
1662 || mep_section_tag (operands[1]) == 'f')
1665 fprintf (stderr, " - no, f\n");
1669 i = mep_section_tag (operands[1]);
1670 if ((i == 'b' || i == 't') && !reload_completed && !reload_in_progress)
1671 /* These are supposed to be generated with adds of the appropriate
1672 register. During and after reload, however, we allow them to
1673 be accessed as normal symbols because adding a dependency on
1674 the base register now might cause problems. */
1677 fprintf (stderr, " - no, bt\n");
1682 /* The only moves we can allow involve at least one general
1683 register, so require it. */
1684 for (i = 0; i < 2; i ++)
1686 /* Allow subregs too, before reload. */
1687 rtx x = operands[i];
1689 if (GET_CODE (x) == SUBREG)
1691 if (GET_CODE (x) == REG
1692 && ! MEP_CONTROL_REG (x))
1695 fprintf (stderr, " - ok\n");
1701 fprintf (stderr, " - no, no gen reg\n");
1706 #define DEBUG_SPLIT_WIDE_MOVE 0
1708 mep_split_wide_move (rtx *operands, enum machine_mode mode)
1712 #if DEBUG_SPLIT_WIDE_MOVE
1713 fprintf (stderr, "\n\033[34mmep_split_wide_move\033[0m mode %s\n", mode_name[mode]);
1714 debug_rtx (operands[0]);
1715 debug_rtx (operands[1]);
1718 for (i = 0; i <= 1; i++)
1720 rtx op = operands[i], hi, lo;
1722 switch (GET_CODE (op))
1726 unsigned int regno = REGNO (op);
1728 if (TARGET_64BIT_CR_REGS && CR_REGNO_P (regno))
1732 lo = gen_rtx_REG (SImode, regno);
1734 hi = gen_rtx_ZERO_EXTRACT (SImode,
1735 gen_rtx_REG (DImode, regno),
1740 hi = gen_rtx_REG (SImode, regno + TARGET_LITTLE_ENDIAN);
1741 lo = gen_rtx_REG (SImode, regno + TARGET_BIG_ENDIAN);
1749 hi = operand_subword (op, TARGET_LITTLE_ENDIAN, 0, mode);
1750 lo = operand_subword (op, TARGET_BIG_ENDIAN, 0, mode);
1757 /* The high part of CR <- GPR moves must be done after the low part. */
1758 operands [i + 4] = lo;
1759 operands [i + 2] = hi;
1762 if (reg_mentioned_p (operands[2], operands[5])
1763 || GET_CODE (operands[2]) == ZERO_EXTRACT
1764 || GET_CODE (operands[4]) == ZERO_EXTRACT)
1768 /* Overlapping register pairs -- make sure we don't
1769 early-clobber ourselves. */
1771 operands[2] = operands[4];
1774 operands[3] = operands[5];
1778 #if DEBUG_SPLIT_WIDE_MOVE
1779 fprintf(stderr, "\033[34m");
1780 debug_rtx (operands[2]);
1781 debug_rtx (operands[3]);
1782 debug_rtx (operands[4]);
1783 debug_rtx (operands[5]);
1784 fprintf(stderr, "\033[0m");
1788 /* Emit a setcc instruction in its entirity. */
1791 mep_expand_setcc_1 (enum rtx_code code, rtx dest, rtx op1, rtx op2)
1799 tmp = op1, op1 = op2, op2 = tmp;
1800 code = swap_condition (code);
1805 op1 = force_reg (SImode, op1);
1806 emit_insn (gen_rtx_SET (VOIDmode, dest,
1807 gen_rtx_fmt_ee (code, SImode, op1, op2)));
1811 if (op2 != const0_rtx)
1812 op1 = expand_binop (SImode, sub_optab, op1, op2, NULL, 1, OPTAB_WIDEN);
1813 mep_expand_setcc_1 (LTU, dest, op1, const1_rtx);
1817 /* Branchful sequence:
1819 beq op1, op2, Lover 16-bit (op2 < 16), 32-bit otherwise
1822 Branchless sequence:
1823 add3 tmp, op1, -op2 32-bit (or mov + sub)
1824 sltu3 tmp, tmp, 1 16-bit
1825 xor3 dest, tmp, 1 32-bit
1827 if (optimize_size && op2 != const0_rtx)
1830 if (op2 != const0_rtx)
1831 op1 = expand_binop (SImode, sub_optab, op1, op2, NULL, 1, OPTAB_WIDEN);
1833 op2 = gen_reg_rtx (SImode);
1834 mep_expand_setcc_1 (LTU, op2, op1, const1_rtx);
1836 emit_insn (gen_rtx_SET (VOIDmode, dest,
1837 gen_rtx_XOR (SImode, op2, const1_rtx)));
1841 if (GET_CODE (op2) != CONST_INT
1842 || INTVAL (op2) == 0x7ffffff)
1844 op2 = GEN_INT (INTVAL (op2) + 1);
1845 return mep_expand_setcc_1 (LT, dest, op1, op2);
1848 if (GET_CODE (op2) != CONST_INT
1849 || INTVAL (op2) == -1)
1851 op2 = GEN_INT (trunc_int_for_mode (INTVAL (op2) + 1, SImode));
1852 return mep_expand_setcc_1 (LTU, dest, op1, op2);
1855 if (GET_CODE (op2) != CONST_INT
1856 || INTVAL (op2) == trunc_int_for_mode (0x80000000, SImode))
1858 op2 = GEN_INT (INTVAL (op2) - 1);
1859 return mep_expand_setcc_1 (GT, dest, op1, op2);
1862 if (GET_CODE (op2) != CONST_INT
1863 || op2 == const0_rtx)
1865 op2 = GEN_INT (trunc_int_for_mode (INTVAL (op2) - 1, SImode));
1866 return mep_expand_setcc_1 (GTU, dest, op1, op2);
1874 mep_expand_setcc (rtx *operands)
1876 rtx dest = operands[0];
1877 enum rtx_code code = GET_CODE (operands[1]);
1878 rtx op0 = operands[2];
1879 rtx op1 = operands[3];
1881 return mep_expand_setcc_1 (code, dest, op0, op1);
1885 mep_expand_cbranch (rtx *operands)
1887 enum rtx_code code = GET_CODE (operands[0]);
1888 rtx op0 = operands[1];
1889 rtx op1 = operands[2];
1896 if (mep_imm4_operand (op1, SImode))
1899 tmp = gen_reg_rtx (SImode);
1900 gcc_assert (mep_expand_setcc_1 (LT, tmp, op0, op1));
1907 if (mep_imm4_operand (op1, SImode))
1910 tmp = gen_reg_rtx (SImode);
1911 gcc_assert (mep_expand_setcc_1 (LT, tmp, op0, op1));
1920 if (! mep_reg_or_imm4_operand (op1, SImode))
1921 op1 = force_reg (SImode, op1);
1926 if (GET_CODE (op1) == CONST_INT
1927 && INTVAL (op1) != 0x7fffffff)
1929 op1 = GEN_INT (INTVAL (op1) + 1);
1930 code = (code == LE ? LT : GE);
1934 tmp = gen_reg_rtx (SImode);
1935 gcc_assert (mep_expand_setcc_1 (LT, tmp, op1, op0));
1937 code = (code == LE ? EQ : NE);
1943 if (op1 == const1_rtx)
1950 tmp = gen_reg_rtx (SImode);
1951 gcc_assert (mep_expand_setcc_1 (LTU, tmp, op0, op1));
1958 tmp = gen_reg_rtx (SImode);
1959 if (mep_expand_setcc_1 (LEU, tmp, op0, op1))
1961 else if (mep_expand_setcc_1 (LTU, tmp, op1, op0))
1970 tmp = gen_reg_rtx (SImode);
1971 gcc_assert (mep_expand_setcc_1 (GTU, tmp, op0, op1)
1972 || mep_expand_setcc_1 (LTU, tmp, op1, op0));
1979 tmp = gen_reg_rtx (SImode);
1980 if (mep_expand_setcc_1 (GEU, tmp, op0, op1))
1982 else if (mep_expand_setcc_1 (LTU, tmp, op0, op1))
1994 return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
1998 mep_emit_cbranch (rtx *operands, int ne)
2000 if (GET_CODE (operands[1]) == REG)
2001 return ne ? "bne\t%0, %1, %l2" : "beq\t%0, %1, %l2";
2002 else if (INTVAL (operands[1]) == 0 && !mep_vliw_function_p(cfun->decl))
2003 return ne ? "bnez\t%0, %l2" : "beqz\t%0, %l2";
2005 return ne ? "bnei\t%0, %1, %l2" : "beqi\t%0, %1, %l2";
2009 mep_expand_call (rtx *operands, int returns_value)
2011 rtx addr = operands[returns_value];
2012 rtx tp = mep_tp_rtx ();
2013 rtx gp = mep_gp_rtx ();
2015 gcc_assert (GET_CODE (addr) == MEM);
2017 addr = XEXP (addr, 0);
2019 if (! mep_call_address_operand (addr, VOIDmode))
2020 addr = force_reg (SImode, addr);
2022 if (! operands[returns_value+2])
2023 operands[returns_value+2] = const0_rtx;
2026 emit_call_insn (gen_call_value_internal (operands[0], addr, operands[2],
2027 operands[3], tp, gp));
2029 emit_call_insn (gen_call_internal (addr, operands[1],
2030 operands[2], tp, gp));
2033 /* Aliasing Support. */
2035 /* If X is a machine specific address (i.e. a symbol or label being
2036 referenced as a displacement from the GOT implemented using an
2037 UNSPEC), then return the base term. Otherwise return X. */
2040 mep_find_base_term (rtx x)
2045 if (GET_CODE (x) != PLUS)
2050 if (has_hard_reg_initial_val(Pmode, TP_REGNO)
2051 && base == mep_tp_rtx ())
2053 else if (has_hard_reg_initial_val(Pmode, GP_REGNO)
2054 && base == mep_gp_rtx ())
2059 if (GET_CODE (term) != CONST)
2061 term = XEXP (term, 0);
2063 if (GET_CODE (term) != UNSPEC
2064 || XINT (term, 1) != unspec)
2067 return XVECEXP (term, 0, 0);
2070 /* Reload Support. */
2072 /* Return true if the registers in CLASS cannot represent the change from
2073 modes FROM to TO. */
2076 mep_cannot_change_mode_class (enum machine_mode from, enum machine_mode to,
2077 enum reg_class regclass)
2082 /* 64-bit COP regs must remain 64-bit COP regs. */
2083 if (TARGET_64BIT_CR_REGS
2084 && (regclass == CR_REGS
2085 || regclass == LOADABLE_CR_REGS)
2086 && (GET_MODE_SIZE (to) < 8
2087 || GET_MODE_SIZE (from) < 8))
2093 #define MEP_NONGENERAL_CLASS(C) (!reg_class_subset_p (C, GENERAL_REGS))
2096 mep_general_reg (rtx x)
2098 while (GET_CODE (x) == SUBREG)
2100 return GET_CODE (x) == REG && GR_REGNO_P (REGNO (x));
2104 mep_nongeneral_reg (rtx x)
2106 while (GET_CODE (x) == SUBREG)
2108 return (GET_CODE (x) == REG
2109 && !GR_REGNO_P (REGNO (x)) && REGNO (x) < FIRST_PSEUDO_REGISTER);
2113 mep_general_copro_reg (rtx x)
2115 while (GET_CODE (x) == SUBREG)
2117 return (GET_CODE (x) == REG && CR_REGNO_P (REGNO (x)));
2121 mep_nonregister (rtx x)
2123 while (GET_CODE (x) == SUBREG)
2125 return (GET_CODE (x) != REG || REGNO (x) >= FIRST_PSEUDO_REGISTER);
2128 #define DEBUG_RELOAD 0
2130 /* Return the secondary reload class needed for moving value X to or
2131 from a register in coprocessor register class CLASS. */
2133 static enum reg_class
2134 mep_secondary_copro_reload_class (enum reg_class rclass, rtx x)
2136 if (mep_general_reg (x))
2137 /* We can do the move directly if mep_have_core_copro_moves_p,
2138 otherwise we need to go through memory. Either way, no secondary
2139 register is needed. */
2142 if (mep_general_copro_reg (x))
2144 /* We can do the move directly if mep_have_copro_copro_moves_p. */
2145 if (mep_have_copro_copro_moves_p)
2148 /* Otherwise we can use a temporary if mep_have_core_copro_moves_p. */
2149 if (mep_have_core_copro_moves_p)
2150 return GENERAL_REGS;
2152 /* Otherwise we need to do it through memory. No secondary
2153 register is needed. */
2157 if (reg_class_subset_p (rclass, LOADABLE_CR_REGS)
2158 && constraint_satisfied_p (x, CONSTRAINT_U))
2159 /* X is a memory value that we can access directly. */
2162 /* We have to move X into a GPR first and then copy it to
2163 the coprocessor register. The move from the GPR to the
2164 coprocessor might be done directly or through memory,
2165 depending on mep_have_core_copro_moves_p. */
2166 return GENERAL_REGS;
2169 /* Copying X to register in RCLASS. */
2172 mep_secondary_input_reload_class (enum reg_class rclass,
2173 enum machine_mode mode ATTRIBUTE_UNUSED,
2179 fprintf (stderr, "secondary input reload copy to %s %s from ", reg_class_names[rclass], mode_name[mode]);
2183 if (reg_class_subset_p (rclass, CR_REGS))
2184 rv = mep_secondary_copro_reload_class (rclass, x);
2185 else if (MEP_NONGENERAL_CLASS (rclass)
2186 && (mep_nonregister (x) || mep_nongeneral_reg (x)))
2190 fprintf (stderr, " - requires %s\n", reg_class_names[rv]);
2195 /* Copying register in RCLASS to X. */
2198 mep_secondary_output_reload_class (enum reg_class rclass,
2199 enum machine_mode mode ATTRIBUTE_UNUSED,
2205 fprintf (stderr, "secondary output reload copy from %s %s to ", reg_class_names[rclass], mode_name[mode]);
2209 if (reg_class_subset_p (rclass, CR_REGS))
2210 rv = mep_secondary_copro_reload_class (rclass, x);
2211 else if (MEP_NONGENERAL_CLASS (rclass)
2212 && (mep_nonregister (x) || mep_nongeneral_reg (x)))
2216 fprintf (stderr, " - requires %s\n", reg_class_names[rv]);
2222 /* Implement SECONDARY_MEMORY_NEEDED. */
2225 mep_secondary_memory_needed (enum reg_class rclass1, enum reg_class rclass2,
2226 enum machine_mode mode ATTRIBUTE_UNUSED)
2228 if (!mep_have_core_copro_moves_p)
2230 if (reg_classes_intersect_p (rclass1, CR_REGS)
2231 && reg_classes_intersect_p (rclass2, GENERAL_REGS))
2233 if (reg_classes_intersect_p (rclass2, CR_REGS)
2234 && reg_classes_intersect_p (rclass1, GENERAL_REGS))
2236 if (!mep_have_copro_copro_moves_p
2237 && reg_classes_intersect_p (rclass1, CR_REGS)
2238 && reg_classes_intersect_p (rclass2, CR_REGS))
2245 mep_expand_reload (rtx *operands, enum machine_mode mode)
2247 /* There are three cases for each direction:
2252 int s0 = mep_section_tag (operands[0]) == 'f';
2253 int s1 = mep_section_tag (operands[1]) == 'f';
2254 int c0 = mep_nongeneral_reg (operands[0]);
2255 int c1 = mep_nongeneral_reg (operands[1]);
2256 int which = (s0 ? 20:0) + (c0 ? 10:0) + (s1 ? 2:0) + (c1 ? 1:0);
2259 fprintf (stderr, "expand_reload %s\n", mode_name[mode]);
2260 debug_rtx (operands[0]);
2261 debug_rtx (operands[1]);
2266 case 00: /* Don't know why this gets here. */
2267 case 02: /* general = far */
2268 emit_move_insn (operands[0], operands[1]);
2271 case 10: /* cr = mem */
2272 case 11: /* cr = cr */
2273 case 01: /* mem = cr */
2274 case 12: /* cr = far */
2275 emit_move_insn (operands[2], operands[1]);
2276 emit_move_insn (operands[0], operands[2]);
2279 case 20: /* far = general */
2280 emit_move_insn (operands[2], XEXP (operands[1], 0));
2281 emit_move_insn (operands[0], gen_rtx_MEM (mode, operands[2]));
2284 case 21: /* far = cr */
2285 case 22: /* far = far */
2287 fprintf (stderr, "unsupported expand reload case %02d for mode %s\n",
2288 which, mode_name[mode]);
2289 debug_rtx (operands[0]);
2290 debug_rtx (operands[1]);
2295 /* Implement PREFERRED_RELOAD_CLASS. See whether X is a constant that
2296 can be moved directly into registers 0 to 7, but not into the rest.
2297 If so, and if the required class includes registers 0 to 7, restrict
2298 it to those registers. */
2301 mep_preferred_reload_class (rtx x, enum reg_class rclass)
2303 switch (GET_CODE (x))
2306 if (INTVAL (x) >= 0x10000
2307 && INTVAL (x) < 0x01000000
2308 && (INTVAL (x) & 0xffff) != 0
2309 && reg_class_subset_p (TPREL_REGS, rclass))
2310 rclass = TPREL_REGS;
2316 if (mep_section_tag (x) != 'f'
2317 && reg_class_subset_p (TPREL_REGS, rclass))
2318 rclass = TPREL_REGS;
2327 /* Implement REGISTER_MOVE_COST. Return 2 for direct single-register
2328 moves, 4 for direct double-register moves, and 1000 for anything
2329 that requires a temporary register or temporary stack slot. */
2332 mep_register_move_cost (enum machine_mode mode, enum reg_class from, enum reg_class to)
2334 if (mep_have_copro_copro_moves_p
2335 && reg_class_subset_p (from, CR_REGS)
2336 && reg_class_subset_p (to, CR_REGS))
2338 if (TARGET_32BIT_CR_REGS && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2342 if (reg_class_subset_p (from, CR_REGS)
2343 && reg_class_subset_p (to, CR_REGS))
2345 if (TARGET_32BIT_CR_REGS && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2349 if (reg_class_subset_p (from, CR_REGS)
2350 || reg_class_subset_p (to, CR_REGS))
2352 if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2356 if (mep_secondary_memory_needed (from, to, mode))
2358 if (MEP_NONGENERAL_CLASS (from) && MEP_NONGENERAL_CLASS (to))
2361 if (GET_MODE_SIZE (mode) > 4)
2368 /* Functions to save and restore machine-specific function data. */
2370 static struct machine_function *
2371 mep_init_machine_status (void)
2373 struct machine_function *f;
2375 f = (struct machine_function *) ggc_alloc_cleared (sizeof (struct machine_function));
2381 mep_allocate_initial_value (rtx reg)
2385 if (GET_CODE (reg) != REG)
2388 if (REGNO (reg) >= FIRST_PSEUDO_REGISTER)
2391 /* In interrupt functions, the "initial" values of $gp and $tp are
2392 provided by the prologue. They are not necessarily the same as
2393 the values that the caller was using. */
2394 if (REGNO (reg) == TP_REGNO || REGNO (reg) == GP_REGNO)
2395 if (mep_interrupt_p ())
2398 if (! cfun->machine->reg_save_slot[REGNO(reg)])
2400 cfun->machine->reg_save_size += 4;
2401 cfun->machine->reg_save_slot[REGNO(reg)] = cfun->machine->reg_save_size;
2404 rss = cfun->machine->reg_save_slot[REGNO(reg)];
2405 return gen_rtx_MEM (SImode, plus_constant (arg_pointer_rtx, -rss));
2409 mep_return_addr_rtx (int count)
2414 return get_hard_reg_initial_val (Pmode, LP_REGNO);
2420 return get_hard_reg_initial_val (Pmode, TP_REGNO);
2426 return get_hard_reg_initial_val (Pmode, GP_REGNO);
2430 mep_interrupt_p (void)
2432 if (cfun->machine->interrupt_handler == 0)
2434 int interrupt_handler
2435 = (lookup_attribute ("interrupt",
2436 DECL_ATTRIBUTES (current_function_decl))
2438 cfun->machine->interrupt_handler = interrupt_handler ? 2 : 1;
2440 return cfun->machine->interrupt_handler == 2;
2444 mep_disinterrupt_p (void)
2446 if (cfun->machine->disable_interrupts == 0)
2448 int disable_interrupts
2449 = (lookup_attribute ("disinterrupt",
2450 DECL_ATTRIBUTES (current_function_decl))
2452 cfun->machine->disable_interrupts = disable_interrupts ? 2 : 1;
2454 return cfun->machine->disable_interrupts == 2;
2458 /* Frame/Epilog/Prolog Related. */
2461 mep_reg_set_p (rtx reg, rtx insn)
2463 /* Similar to reg_set_p in rtlanal.c, but we ignore calls */
2466 if (FIND_REG_INC_NOTE (insn, reg))
2468 insn = PATTERN (insn);
2471 if (GET_CODE (insn) == SET
2472 && GET_CODE (XEXP (insn, 0)) == REG
2473 && GET_CODE (XEXP (insn, 1)) == REG
2474 && REGNO (XEXP (insn, 0)) == REGNO (XEXP (insn, 1)))
2477 return set_of (reg, insn) != NULL_RTX;
2481 #define MEP_SAVES_UNKNOWN 0
2482 #define MEP_SAVES_YES 1
2483 #define MEP_SAVES_MAYBE 2
2484 #define MEP_SAVES_NO 3
2487 mep_reg_set_in_function (int regno)
2491 if (mep_interrupt_p () && df_regs_ever_live_p(regno))
2494 if (regno == LP_REGNO && (profile_arc_flag > 0 || profile_flag > 0))
2497 push_topmost_sequence ();
2498 insn = get_insns ();
2499 pop_topmost_sequence ();
2504 reg = gen_rtx_REG (SImode, regno);
2506 for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
2507 if (INSN_P (insn) && mep_reg_set_p (reg, insn))
2513 mep_asm_without_operands_p (void)
2515 if (cfun->machine->asms_without_operands == 0)
2519 push_topmost_sequence ();
2520 insn = get_insns ();
2521 pop_topmost_sequence ();
2523 cfun->machine->asms_without_operands = 1;
2527 && GET_CODE (PATTERN (insn)) == ASM_INPUT)
2529 cfun->machine->asms_without_operands = 2;
2532 insn = NEXT_INSN (insn);
2536 return cfun->machine->asms_without_operands == 2;
2539 /* Interrupt functions save/restore every call-preserved register, and
2540 any call-used register it uses (or all if it calls any function,
2541 since they may get clobbered there too). Here we check to see
2542 which call-used registers need saving. */
2544 #define IVC2_ISAVED_REG(r) (TARGET_IVC2 \
2545 && (r == FIRST_CCR_REGNO + 1 \
2546 || (r >= FIRST_CCR_REGNO + 8 && r <= FIRST_CCR_REGNO + 11) \
2547 || (r >= FIRST_CCR_REGNO + 16 && r <= FIRST_CCR_REGNO + 31)))
2550 mep_interrupt_saved_reg (int r)
2552 if (!mep_interrupt_p ())
2554 if (r == REGSAVE_CONTROL_TEMP
2555 || (TARGET_64BIT_CR_REGS && TARGET_COP && r == REGSAVE_CONTROL_TEMP+1))
2557 if (mep_asm_without_operands_p ()
2559 || (r == RPB_REGNO || r == RPE_REGNO || r == RPC_REGNO || r == LP_REGNO)
2560 || IVC2_ISAVED_REG (r)))
2562 if (!current_function_is_leaf)
2563 /* Function calls mean we need to save $lp. */
2564 if (r == LP_REGNO || IVC2_ISAVED_REG (r))
2566 if (!current_function_is_leaf || cfun->machine->doloop_tags > 0)
2567 /* The interrupt handler might use these registers for repeat blocks,
2568 or it might call a function that does so. */
2569 if (r == RPB_REGNO || r == RPE_REGNO || r == RPC_REGNO)
2571 if (current_function_is_leaf && call_used_regs[r] && !df_regs_ever_live_p(r))
2573 /* Functions we call might clobber these. */
2574 if (call_used_regs[r] && !fixed_regs[r])
2576 /* Additional registers that need to be saved for IVC2. */
2577 if (IVC2_ISAVED_REG (r))
2584 mep_call_saves_register (int r)
2586 if (! cfun->machine->frame_locked)
2588 int rv = MEP_SAVES_NO;
2590 if (cfun->machine->reg_save_slot[r])
2592 else if (r == LP_REGNO && (profile_arc_flag > 0 || profile_flag > 0))
2594 else if (r == FRAME_POINTER_REGNUM && frame_pointer_needed)
2596 else if ((!call_used_regs[r] || r == LP_REGNO) && df_regs_ever_live_p(r))
2598 else if (crtl->calls_eh_return && (r == 10 || r == 11))
2599 /* We need these to have stack slots so that they can be set during
2602 else if (mep_interrupt_saved_reg (r))
2604 cfun->machine->reg_saved[r] = rv;
2606 return cfun->machine->reg_saved[r] == MEP_SAVES_YES;
2609 /* Return true if epilogue uses register REGNO. */
2612 mep_epilogue_uses (int regno)
2614 /* Since $lp is a call-saved register, the generic code will normally
2615 mark it used in the epilogue if it needs to be saved and restored.
2616 However, when profiling is enabled, the profiling code will implicitly
2617 clobber $11. This case has to be handled specially both here and in
2618 mep_call_saves_register. */
2619 if (regno == LP_REGNO && (profile_arc_flag > 0 || profile_flag > 0))
2621 /* Interrupt functions save/restore pretty much everything. */
2622 return (reload_completed && mep_interrupt_saved_reg (regno));
2626 mep_reg_size (int regno)
2628 if (CR_REGNO_P (regno) && TARGET_64BIT_CR_REGS)
2633 /* Worker function for TARGET_CAN_ELIMINATE. */
2636 mep_can_eliminate (const int from, const int to)
2638 return (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM
2639 ? ! frame_pointer_needed
2644 mep_elimination_offset (int from, int to)
2648 int frame_size = get_frame_size () + crtl->outgoing_args_size;
2651 if (!cfun->machine->frame_locked)
2652 memset (cfun->machine->reg_saved, 0, sizeof (cfun->machine->reg_saved));
2654 /* We don't count arg_regs_to_save in the arg pointer offset, because
2655 gcc thinks the arg pointer has moved along with the saved regs.
2656 However, we do count it when we adjust $sp in the prologue. */
2658 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2659 if (mep_call_saves_register (i))
2660 reg_save_size += mep_reg_size (i);
2662 if (reg_save_size % 8)
2663 cfun->machine->regsave_filler = 8 - (reg_save_size % 8);
2665 cfun->machine->regsave_filler = 0;
2667 /* This is what our total stack adjustment looks like. */
2668 total_size = (reg_save_size + frame_size + cfun->machine->regsave_filler);
2671 cfun->machine->frame_filler = 8 - (total_size % 8);
2673 cfun->machine->frame_filler = 0;
2676 if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
2677 return reg_save_size + cfun->machine->regsave_filler;
2679 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
2680 return cfun->machine->frame_filler + frame_size;
2682 if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
2683 return reg_save_size + cfun->machine->regsave_filler + cfun->machine->frame_filler + frame_size;
2691 RTX_FRAME_RELATED_P (x) = 1;
2695 /* Since the prologue/epilogue code is generated after optimization,
2696 we can't rely on gcc to split constants for us. So, this code
2697 captures all the ways to add a constant to a register in one logic
2698 chunk, including optimizing away insns we just don't need. This
2699 makes the prolog/epilog code easier to follow. */
2701 add_constant (int dest, int src, int value, int mark_frame)
2706 if (src == dest && value == 0)
2711 insn = emit_move_insn (gen_rtx_REG (SImode, dest),
2712 gen_rtx_REG (SImode, src));
2714 RTX_FRAME_RELATED_P(insn) = 1;
2718 if (value >= -32768 && value <= 32767)
2720 insn = emit_insn (gen_addsi3 (gen_rtx_REG (SImode, dest),
2721 gen_rtx_REG (SImode, src),
2724 RTX_FRAME_RELATED_P(insn) = 1;
2728 /* Big constant, need to use a temp register. We use
2729 REGSAVE_CONTROL_TEMP because it's call clobberable (the reg save
2730 area is always small enough to directly add to). */
2732 hi = trunc_int_for_mode (value & 0xffff0000, SImode);
2733 lo = value & 0xffff;
2735 insn = emit_move_insn (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2740 insn = emit_insn (gen_iorsi3 (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2741 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2745 insn = emit_insn (gen_addsi3 (gen_rtx_REG (SImode, dest),
2746 gen_rtx_REG (SImode, src),
2747 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP)));
2750 RTX_FRAME_RELATED_P(insn) = 1;
2751 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2752 gen_rtx_SET (SImode,
2753 gen_rtx_REG (SImode, dest),
2754 gen_rtx_PLUS (SImode,
2755 gen_rtx_REG (SImode, dest),
2761 mep_function_uses_sp (void)
2764 struct sequence_stack *seq;
2765 rtx sp = gen_rtx_REG (SImode, SP_REGNO);
2767 insn = get_insns ();
2768 for (seq = crtl->emit.sequence_stack;
2770 insn = seq->first, seq = seq->next);
2774 if (mep_mentioned_p (insn, sp, 0))
2776 insn = NEXT_INSN (insn);
2781 /* Move SRC to DEST. Mark the move as being potentially dead if
2785 maybe_dead_move (rtx dest, rtx src, bool ATTRIBUTE_UNUSED maybe_dead_p)
2787 rtx insn = emit_move_insn (dest, src);
2790 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
2795 /* Used for interrupt functions, which can't assume that $tp and $gp
2796 contain the correct pointers. */
2799 mep_reload_pointer (int regno, const char *symbol)
2803 if (!df_regs_ever_live_p(regno) && current_function_is_leaf)
2806 reg = gen_rtx_REG (SImode, regno);
2807 sym = gen_rtx_SYMBOL_REF (SImode, symbol);
2808 emit_insn (gen_movsi_topsym_s (reg, sym));
2809 emit_insn (gen_movsi_botsym_s (reg, reg, sym));
2812 /* Assign save slots for any register not already saved. DImode
2813 registers go at the end of the reg save area; the rest go at the
2814 beginning. This is for alignment purposes. Returns true if a frame
2815 is really needed. */
2817 mep_assign_save_slots (int reg_save_size)
2819 bool really_need_stack_frame = false;
2823 for (i=0; i<FIRST_PSEUDO_REGISTER; i++)
2824 if (mep_call_saves_register(i))
2826 int regsize = mep_reg_size (i);
2828 if ((i != TP_REGNO && i != GP_REGNO && i != LP_REGNO)
2829 || mep_reg_set_in_function (i))
2830 really_need_stack_frame = true;
2832 if (cfun->machine->reg_save_slot[i])
2837 cfun->machine->reg_save_size += regsize;
2838 cfun->machine->reg_save_slot[i] = cfun->machine->reg_save_size;
2842 cfun->machine->reg_save_slot[i] = reg_save_size - di_ofs;
2846 cfun->machine->frame_locked = 1;
2847 return really_need_stack_frame;
2851 mep_expand_prologue (void)
2853 int i, rss, sp_offset = 0;
2856 int really_need_stack_frame = frame_size;
2858 /* We must not allow register renaming in interrupt functions,
2859 because that invalidates the correctness of the set of call-used
2860 registers we're going to save/restore. */
2861 mep_set_leaf_registers (mep_interrupt_p () ? 0 : 1);
2863 if (mep_disinterrupt_p ())
2864 emit_insn (gen_mep_disable_int ());
2866 cfun->machine->mep_frame_pointer_needed = frame_pointer_needed;
2868 reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
2869 frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
2871 really_need_stack_frame |= mep_assign_save_slots (reg_save_size);
2873 sp_offset = reg_save_size;
2874 if (sp_offset + frame_size < 128)
2875 sp_offset += frame_size ;
2877 add_constant (SP_REGNO, SP_REGNO, -sp_offset, 1);
2879 for (i=0; i<FIRST_PSEUDO_REGISTER; i++)
2880 if (mep_call_saves_register(i))
2884 enum machine_mode rmode;
2886 rss = cfun->machine->reg_save_slot[i];
2888 if ((i == TP_REGNO || i == GP_REGNO || i == LP_REGNO)
2889 && (!mep_reg_set_in_function (i)
2890 && !mep_interrupt_p ()))
2893 if (mep_reg_size (i) == 8)
2898 /* If there is a pseudo associated with this register's initial value,
2899 reload might have already spilt it to the stack slot suggested by
2900 ALLOCATE_INITIAL_VALUE. The moves emitted here can then be safely
2902 mem = gen_rtx_MEM (rmode,
2903 plus_constant (stack_pointer_rtx, sp_offset - rss));
2904 maybe_dead_p = rtx_equal_p (mem, has_hard_reg_initial_val (rmode, i));
2906 if (GR_REGNO_P (i) || LOADABLE_CR_REGNO_P (i))
2907 F(maybe_dead_move (mem, gen_rtx_REG (rmode, i), maybe_dead_p));
2908 else if (rmode == DImode)
2911 int be = TARGET_BIG_ENDIAN ? 4 : 0;
2913 mem = gen_rtx_MEM (SImode,
2914 plus_constant (stack_pointer_rtx, sp_offset - rss + be));
2916 maybe_dead_move (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2917 gen_rtx_REG (SImode, i),
2919 maybe_dead_move (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP+1),
2920 gen_rtx_ZERO_EXTRACT (SImode,
2921 gen_rtx_REG (DImode, i),
2925 insn = maybe_dead_move (mem,
2926 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2928 RTX_FRAME_RELATED_P (insn) = 1;
2930 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2931 gen_rtx_SET (VOIDmode,
2933 gen_rtx_REG (rmode, i)));
2934 mem = gen_rtx_MEM (SImode,
2935 plus_constant (stack_pointer_rtx, sp_offset - rss + (4-be)));
2936 insn = maybe_dead_move (mem,
2937 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP+1),
2943 maybe_dead_move (gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
2944 gen_rtx_REG (rmode, i),
2946 insn = maybe_dead_move (mem,
2947 gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
2949 RTX_FRAME_RELATED_P (insn) = 1;
2951 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2952 gen_rtx_SET (VOIDmode,
2954 gen_rtx_REG (rmode, i)));
2958 if (frame_pointer_needed)
2960 /* We've already adjusted down by sp_offset. Total $sp change
2961 is reg_save_size + frame_size. We want a net change here of
2962 just reg_save_size. */
2963 add_constant (FP_REGNO, SP_REGNO, sp_offset - reg_save_size, 1);
2966 add_constant (SP_REGNO, SP_REGNO, sp_offset-(reg_save_size+frame_size), 1);
2968 if (mep_interrupt_p ())
2970 mep_reload_pointer(GP_REGNO, "__sdabase");
2971 mep_reload_pointer(TP_REGNO, "__tpbase");
2976 mep_start_function (FILE *file, HOST_WIDE_INT hwi_local)
2978 int local = hwi_local;
2979 int frame_size = local + crtl->outgoing_args_size;
2984 int slot_map[FIRST_PSEUDO_REGISTER], si, sj;
2986 reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
2987 frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
2988 sp_offset = reg_save_size + frame_size;
2990 ffill = cfun->machine->frame_filler;
2992 if (cfun->machine->mep_frame_pointer_needed)
2993 reg_names[FP_REGNO] = "$fp";
2995 reg_names[FP_REGNO] = "$8";
3000 if (debug_info_level == DINFO_LEVEL_NONE)
3002 fprintf (file, "\t# frame: %d", sp_offset);
3004 fprintf (file, " %d regs", reg_save_size);
3006 fprintf (file, " %d locals", local);
3007 if (crtl->outgoing_args_size)
3008 fprintf (file, " %d args", crtl->outgoing_args_size);
3009 fprintf (file, "\n");
3013 fprintf (file, "\t#\n");
3014 fprintf (file, "\t# Initial Frame Information:\n");
3015 if (sp_offset || !frame_pointer_needed)
3016 fprintf (file, "\t# Entry ---------- 0\n");
3018 /* Sort registers by save slots, so they're printed in the order
3019 they appear in memory, not the order they're saved in. */
3020 for (si=0; si<FIRST_PSEUDO_REGISTER; si++)
3022 for (si=0; si<FIRST_PSEUDO_REGISTER-1; si++)
3023 for (sj=si+1; sj<FIRST_PSEUDO_REGISTER; sj++)
3024 if (cfun->machine->reg_save_slot[slot_map[si]]
3025 > cfun->machine->reg_save_slot[slot_map[sj]])
3027 int t = slot_map[si];
3028 slot_map[si] = slot_map[sj];
3033 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3036 int r = slot_map[i];
3037 int rss = cfun->machine->reg_save_slot[r];
3039 if (!mep_call_saves_register (r))
3042 if ((r == TP_REGNO || r == GP_REGNO || r == LP_REGNO)
3043 && (!mep_reg_set_in_function (r)
3044 && !mep_interrupt_p ()))
3047 rsize = mep_reg_size(r);
3048 skip = rss - (sp+rsize);
3050 fprintf (file, "\t# %3d bytes for alignment\n", skip);
3051 fprintf (file, "\t# %3d bytes for saved %-3s %3d($sp)\n",
3052 rsize, reg_names[r], sp_offset - rss);
3056 skip = reg_save_size - sp;
3058 fprintf (file, "\t# %3d bytes for alignment\n", skip);
3060 if (frame_pointer_needed)
3061 fprintf (file, "\t# FP ---> ---------- %d (sp-%d)\n", reg_save_size, sp_offset-reg_save_size);
3063 fprintf (file, "\t# %3d bytes for local vars\n", local);
3065 fprintf (file, "\t# %3d bytes for alignment\n", ffill);
3066 if (crtl->outgoing_args_size)
3067 fprintf (file, "\t# %3d bytes for outgoing args\n",
3068 crtl->outgoing_args_size);
3069 fprintf (file, "\t# SP ---> ---------- %d\n", sp_offset);
3070 fprintf (file, "\t#\n");
3074 static int mep_prevent_lp_restore = 0;
3075 static int mep_sibcall_epilogue = 0;
3078 mep_expand_epilogue (void)
3080 int i, sp_offset = 0;
3081 int reg_save_size = 0;
3083 int lp_temp = LP_REGNO, lp_slot = -1;
3084 int really_need_stack_frame = get_frame_size() + crtl->outgoing_args_size;
3085 int interrupt_handler = mep_interrupt_p ();
3087 if (profile_arc_flag == 2)
3088 emit_insn (gen_mep_bb_trace_ret ());
3090 reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
3091 frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
3093 really_need_stack_frame |= mep_assign_save_slots (reg_save_size);
3095 if (frame_pointer_needed)
3097 /* If we have a frame pointer, we won't have a reliable stack
3098 pointer (alloca, you know), so rebase SP from FP */
3099 emit_move_insn (gen_rtx_REG (SImode, SP_REGNO),
3100 gen_rtx_REG (SImode, FP_REGNO));
3101 sp_offset = reg_save_size;
3105 /* SP is right under our local variable space. Adjust it if
3107 sp_offset = reg_save_size + frame_size;
3108 if (sp_offset >= 128)
3110 add_constant (SP_REGNO, SP_REGNO, frame_size, 0);
3111 sp_offset -= frame_size;
3115 /* This is backwards so that we restore the control and coprocessor
3116 registers before the temporary registers we use to restore
3118 for (i=FIRST_PSEUDO_REGISTER-1; i>=1; i--)
3119 if (mep_call_saves_register (i))
3121 enum machine_mode rmode;
3122 int rss = cfun->machine->reg_save_slot[i];
3124 if (mep_reg_size (i) == 8)
3129 if ((i == TP_REGNO || i == GP_REGNO || i == LP_REGNO)
3130 && !(mep_reg_set_in_function (i) || interrupt_handler))
3132 if (mep_prevent_lp_restore && i == LP_REGNO)
3134 if (!mep_prevent_lp_restore
3135 && !interrupt_handler
3136 && (i == 10 || i == 11))
3139 if (GR_REGNO_P (i) || LOADABLE_CR_REGNO_P (i))
3140 emit_move_insn (gen_rtx_REG (rmode, i),
3142 plus_constant (stack_pointer_rtx,
3146 if (i == LP_REGNO && !mep_sibcall_epilogue && !interrupt_handler)
3147 /* Defer this one so we can jump indirect rather than
3148 copying the RA to $lp and "ret". EH epilogues
3149 automatically skip this anyway. */
3150 lp_slot = sp_offset-rss;
3153 emit_move_insn (gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
3155 plus_constant (stack_pointer_rtx,
3157 emit_move_insn (gen_rtx_REG (rmode, i),
3158 gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP));
3164 /* Restore this one last so we know it will be in the temp
3165 register when we return by jumping indirectly via the temp. */
3166 emit_move_insn (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
3167 gen_rtx_MEM (SImode,
3168 plus_constant (stack_pointer_rtx,
3170 lp_temp = REGSAVE_CONTROL_TEMP;
3174 add_constant (SP_REGNO, SP_REGNO, sp_offset, 0);
3176 if (crtl->calls_eh_return && mep_prevent_lp_restore)
3177 emit_insn (gen_addsi3 (gen_rtx_REG (SImode, SP_REGNO),
3178 gen_rtx_REG (SImode, SP_REGNO),
3179 cfun->machine->eh_stack_adjust));
3181 if (mep_sibcall_epilogue)
3184 if (mep_disinterrupt_p ())
3185 emit_insn (gen_mep_enable_int ());
3187 if (mep_prevent_lp_restore)
3189 emit_jump_insn (gen_eh_return_internal ());
3192 else if (interrupt_handler)
3193 emit_jump_insn (gen_mep_reti ());
3195 emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode, lp_temp)));
3199 mep_expand_eh_return (rtx *operands)
3201 if (GET_CODE (operands[0]) != REG || REGNO (operands[0]) != LP_REGNO)
3203 rtx ra = gen_rtx_REG (Pmode, LP_REGNO);
3204 emit_move_insn (ra, operands[0]);
3208 emit_insn (gen_eh_epilogue (operands[0]));
3212 mep_emit_eh_epilogue (rtx *operands ATTRIBUTE_UNUSED)
3214 cfun->machine->eh_stack_adjust = gen_rtx_REG (Pmode, 0);
3215 mep_prevent_lp_restore = 1;
3216 mep_expand_epilogue ();
3217 mep_prevent_lp_restore = 0;
3221 mep_expand_sibcall_epilogue (void)
3223 mep_sibcall_epilogue = 1;
3224 mep_expand_epilogue ();
3225 mep_sibcall_epilogue = 0;
3229 mep_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
3234 if (mep_section_tag (DECL_RTL (decl)) == 'f')
3237 /* Can't call to a sibcall from an interrupt or disinterrupt function. */
3238 if (mep_interrupt_p () || mep_disinterrupt_p ())
3245 mep_return_stackadj_rtx (void)
3247 return gen_rtx_REG (SImode, 10);
3251 mep_return_handler_rtx (void)
3253 return gen_rtx_REG (SImode, LP_REGNO);
3257 mep_function_profiler (FILE *file)
3259 /* Always right at the beginning of the function. */
3260 fprintf (file, "\t# mep function profiler\n");
3261 fprintf (file, "\tadd\t$sp, -8\n");
3262 fprintf (file, "\tsw\t$0, ($sp)\n");
3263 fprintf (file, "\tldc\t$0, $lp\n");
3264 fprintf (file, "\tsw\t$0, 4($sp)\n");
3265 fprintf (file, "\tbsr\t__mep_mcount\n");
3266 fprintf (file, "\tlw\t$0, 4($sp)\n");
3267 fprintf (file, "\tstc\t$0, $lp\n");
3268 fprintf (file, "\tlw\t$0, ($sp)\n");
3269 fprintf (file, "\tadd\t$sp, 8\n\n");
3273 mep_emit_bb_trace_ret (void)
3275 fprintf (asm_out_file, "\t# end of block profiling\n");
3276 fprintf (asm_out_file, "\tadd\t$sp, -8\n");
3277 fprintf (asm_out_file, "\tsw\t$0, ($sp)\n");
3278 fprintf (asm_out_file, "\tldc\t$0, $lp\n");
3279 fprintf (asm_out_file, "\tsw\t$0, 4($sp)\n");
3280 fprintf (asm_out_file, "\tbsr\t__bb_trace_ret\n");
3281 fprintf (asm_out_file, "\tlw\t$0, 4($sp)\n");
3282 fprintf (asm_out_file, "\tstc\t$0, $lp\n");
3283 fprintf (asm_out_file, "\tlw\t$0, ($sp)\n");
3284 fprintf (asm_out_file, "\tadd\t$sp, 8\n\n");
3291 /* Operand Printing. */
3294 mep_print_operand_address (FILE *stream, rtx address)
3296 if (GET_CODE (address) == MEM)
3297 address = XEXP (address, 0);
3299 /* cf: gcc.dg/asm-4.c. */
3300 gcc_assert (GET_CODE (address) == REG);
3302 mep_print_operand (stream, address, 0);
3308 const char *pattern;
3311 const conversions[] =
3314 { 0, "m+ri", "3(2)" },
3318 { 0, "mLrs", "%lo(3)(2)" },
3319 { 0, "mLr+si", "%lo(4+5)(2)" },
3320 { 0, "m+ru2s", "%tpoff(5)(2)" },
3321 { 0, "m+ru3s", "%sdaoff(5)(2)" },
3322 { 0, "m+r+u2si", "%tpoff(6+7)(2)" },
3323 { 0, "m+ru2+si", "%tpoff(6+7)(2)" },
3324 { 0, "m+r+u3si", "%sdaoff(6+7)(2)" },
3325 { 0, "m+ru3+si", "%sdaoff(6+7)(2)" },
3327 { 0, "m+si", "(2+3)" },
3328 { 0, "m+li", "(2+3)" },
3331 { 0, "+si", "1+2" },
3332 { 0, "+u2si", "%tpoff(3+4)" },
3333 { 0, "+u3si", "%sdaoff(3+4)" },
3339 { 'h', "Hs", "%hi(1)" },
3341 { 'I', "u2s", "%tpoff(2)" },
3342 { 'I', "u3s", "%sdaoff(2)" },
3343 { 'I', "+u2si", "%tpoff(3+4)" },
3344 { 'I', "+u3si", "%sdaoff(3+4)" },
3346 { 'P', "mr", "(1\\+),\\0" },
3352 unique_bit_in (HOST_WIDE_INT i)
3356 case 0x01: case 0xfe: return 0;
3357 case 0x02: case 0xfd: return 1;
3358 case 0x04: case 0xfb: return 2;
3359 case 0x08: case 0xf7: return 3;
3360 case 0x10: case 0x7f: return 4;
3361 case 0x20: case 0xbf: return 5;
3362 case 0x40: case 0xdf: return 6;
3363 case 0x80: case 0xef: return 7;
3370 bit_size_for_clip (HOST_WIDE_INT i)
3374 for (rv = 0; rv < 31; rv ++)
3375 if (((HOST_WIDE_INT) 1 << rv) > i)
3380 /* Print an operand to a assembler instruction. */
3383 mep_print_operand (FILE *file, rtx x, int code)
3386 const char *real_name;
3390 /* Print a mnemonic to do CR <- CR moves. Find out which intrinsic
3391 we're using, then skip over the "mep_" part of its name. */
3392 const struct cgen_insn *insn;
3394 if (mep_get_move_insn (mep_cmov, &insn))
3395 fputs (cgen_intrinsics[insn->intrinsic] + 4, file);
3397 mep_intrinsic_unavailable (mep_cmov);
3402 switch (GET_CODE (x))
3405 fputs ("clr", file);
3408 fputs ("set", file);
3411 fputs ("not", file);
3414 output_operand_lossage ("invalid %%L code");
3419 /* Print the second operand of a CR <- CR move. If we're using
3420 a two-operand instruction (i.e., a real cmov), then just print
3421 the operand normally. If we're using a "reg, reg, immediate"
3422 instruction such as caddi3, print the operand followed by a
3423 zero field. If we're using a three-register instruction,
3424 print the operand twice. */
3425 const struct cgen_insn *insn;
3427 mep_print_operand (file, x, 0);
3428 if (mep_get_move_insn (mep_cmov, &insn)
3429 && insn_data[insn->icode].n_operands == 3)
3432 if (insn_data[insn->icode].operand[2].predicate (x, VOIDmode))
3433 mep_print_operand (file, x, 0);
3435 mep_print_operand (file, const0_rtx, 0);
3441 for (i = 0; conversions[i].pattern; i++)
3442 if (conversions[i].code == code
3443 && strcmp(conversions[i].pattern, pattern) == 0)
3445 for (j = 0; conversions[i].format[j]; j++)
3446 if (conversions[i].format[j] == '\\')
3448 fputc (conversions[i].format[j+1], file);
3451 else if (ISDIGIT(conversions[i].format[j]))
3453 rtx r = patternr[conversions[i].format[j] - '0'];
3454 switch (GET_CODE (r))
3457 fprintf (file, "%s", reg_names [REGNO (r)]);
3463 fprintf (file, "%d", unique_bit_in (INTVAL (r)));
3466 fprintf (file, "%d", bit_size_for_clip (INTVAL (r)));
3469 fprintf (file, "0x%x", ((int) INTVAL (r) >> 16) & 0xffff);
3472 fprintf (file, "%d", bit_size_for_clip (INTVAL (r)) - 1);
3475 fprintf (file, "0x%x", (int) INTVAL (r) & 0xffff);
3478 if (INTVAL (r) & ~(HOST_WIDE_INT)0xff
3479 && !(INTVAL (r) & 0xff))
3480 fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL(r));
3482 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3485 if (INTVAL (r) & ~(HOST_WIDE_INT)0xff
3486 && conversions[i].format[j+1] == 0)
3488 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (r));
3489 fprintf (file, " # 0x%x", (int) INTVAL(r) & 0xffff);
3492 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3495 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3500 fprintf(file, "[const_double 0x%lx]",
3501 (unsigned long) CONST_DOUBLE_HIGH(r));
3504 real_name = TARGET_STRIP_NAME_ENCODING (XSTR (r, 0));
3505 assemble_name (file, real_name);
3508 output_asm_label (r);
3511 fprintf (stderr, "don't know how to print this operand:");
3518 if (conversions[i].format[j] == '+'
3519 && (!code || code == 'I')
3520 && ISDIGIT (conversions[i].format[j+1])
3521 && GET_CODE (patternr[conversions[i].format[j+1] - '0']) == CONST_INT
3522 && INTVAL (patternr[conversions[i].format[j+1] - '0']) < 0)
3524 fputc(conversions[i].format[j], file);
3528 if (!conversions[i].pattern)
3530 error ("unconvertible operand %c %qs", code?code:'-', pattern);
3538 mep_final_prescan_insn (rtx insn, rtx *operands ATTRIBUTE_UNUSED,
3539 int noperands ATTRIBUTE_UNUSED)
3541 /* Despite the fact that MeP is perfectly capable of branching and
3542 doing something else in the same bundle, gcc does jump
3543 optimization *after* scheduling, so we cannot trust the bundling
3544 flags on jump instructions. */
3545 if (GET_MODE (insn) == BImode
3546 && get_attr_slots (insn) != SLOTS_CORE)
3547 fputc ('+', asm_out_file);
3550 /* Function args in registers. */
3553 mep_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
3554 enum machine_mode mode ATTRIBUTE_UNUSED,
3555 tree type ATTRIBUTE_UNUSED, int *pretend_size,
3556 int second_time ATTRIBUTE_UNUSED)
3558 int nsave = 4 - (cum->nregs + 1);
3561 cfun->machine->arg_regs_to_save = nsave;
3562 *pretend_size = nsave * 4;
3566 bytesize (const_tree type, enum machine_mode mode)
3568 if (mode == BLKmode)
3569 return int_size_in_bytes (type);
3570 return GET_MODE_SIZE (mode);
3574 mep_expand_builtin_saveregs (void)
3579 ns = cfun->machine->arg_regs_to_save;
3582 bufsize = 8 * ((ns + 1) / 2) + 8 * ns;
3583 regbuf = assign_stack_local (SImode, bufsize, 64);
3588 regbuf = assign_stack_local (SImode, bufsize, 32);
3591 move_block_from_reg (5-ns, regbuf, ns);
3595 rtx tmp = gen_rtx_MEM (DImode, XEXP (regbuf, 0));
3596 int ofs = 8 * ((ns+1)/2);
3598 for (i=0; i<ns; i++)
3600 int rn = (4-ns) + i + 49;
3603 ptr = offset_address (tmp, GEN_INT (ofs), 2);
3604 emit_move_insn (ptr, gen_rtx_REG (DImode, rn));
3608 return XEXP (regbuf, 0);
3611 #define VECTOR_TYPE_P(t) (TREE_CODE(t) == VECTOR_TYPE)
3614 mep_build_builtin_va_list (void)
3616 tree f_next_gp, f_next_gp_limit, f_next_cop, f_next_stack;
3620 record = (*lang_hooks.types.make_type) (RECORD_TYPE);
3622 f_next_gp = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3623 get_identifier ("__va_next_gp"), ptr_type_node);
3624 f_next_gp_limit = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3625 get_identifier ("__va_next_gp_limit"),
3627 f_next_cop = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("__va_next_cop"),
3629 f_next_stack = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("__va_next_stack"),
3632 DECL_FIELD_CONTEXT (f_next_gp) = record;
3633 DECL_FIELD_CONTEXT (f_next_gp_limit) = record;
3634 DECL_FIELD_CONTEXT (f_next_cop) = record;
3635 DECL_FIELD_CONTEXT (f_next_stack) = record;
3637 TYPE_FIELDS (record) = f_next_gp;
3638 TREE_CHAIN (f_next_gp) = f_next_gp_limit;
3639 TREE_CHAIN (f_next_gp_limit) = f_next_cop;
3640 TREE_CHAIN (f_next_cop) = f_next_stack;
3642 layout_type (record);
3648 mep_expand_va_start (tree valist, rtx nextarg)
3650 tree f_next_gp, f_next_gp_limit, f_next_cop, f_next_stack;
3651 tree next_gp, next_gp_limit, next_cop, next_stack;
3655 ns = cfun->machine->arg_regs_to_save;
3657 f_next_gp = TYPE_FIELDS (va_list_type_node);
3658 f_next_gp_limit = TREE_CHAIN (f_next_gp);
3659 f_next_cop = TREE_CHAIN (f_next_gp_limit);
3660 f_next_stack = TREE_CHAIN (f_next_cop);
3662 next_gp = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp), valist, f_next_gp,
3664 next_gp_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp_limit),
3665 valist, f_next_gp_limit, NULL_TREE);
3666 next_cop = build3 (COMPONENT_REF, TREE_TYPE (f_next_cop), valist, f_next_cop,
3668 next_stack = build3 (COMPONENT_REF, TREE_TYPE (f_next_stack),
3669 valist, f_next_stack, NULL_TREE);
3671 /* va_list.next_gp = expand_builtin_saveregs (); */
3672 u = make_tree (sizetype, expand_builtin_saveregs ());
3673 u = fold_convert (ptr_type_node, u);
3674 t = build2 (MODIFY_EXPR, ptr_type_node, next_gp, u);
3675 TREE_SIDE_EFFECTS (t) = 1;
3676 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3678 /* va_list.next_gp_limit = va_list.next_gp + 4 * ns; */
3679 u = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, u,
3681 t = build2 (MODIFY_EXPR, ptr_type_node, next_gp_limit, u);
3682 TREE_SIDE_EFFECTS (t) = 1;
3683 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3685 u = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, u,
3686 size_int (8 * ((ns+1)/2)));
3687 /* va_list.next_cop = ROUND_UP(va_list.next_gp_limit,8); */
3688 t = build2 (MODIFY_EXPR, ptr_type_node, next_cop, u);
3689 TREE_SIDE_EFFECTS (t) = 1;
3690 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3692 /* va_list.next_stack = nextarg; */
3693 u = make_tree (ptr_type_node, nextarg);
3694 t = build2 (MODIFY_EXPR, ptr_type_node, next_stack, u);
3695 TREE_SIDE_EFFECTS (t) = 1;
3696 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3700 mep_gimplify_va_arg_expr (tree valist, tree type,
3701 tree *pre_p, tree *post_p ATTRIBUTE_UNUSED)
3703 HOST_WIDE_INT size, rsize;
3704 bool by_reference, ivc2_vec;
3705 tree f_next_gp, f_next_gp_limit, f_next_cop, f_next_stack;
3706 tree next_gp, next_gp_limit, next_cop, next_stack;
3707 tree label_sover, label_selse;
3710 ivc2_vec = TARGET_IVC2 && VECTOR_TYPE_P (type);
3712 size = int_size_in_bytes (type);
3713 by_reference = (size > (ivc2_vec ? 8 : 4)) || (size <= 0);
3717 type = build_pointer_type (type);
3720 rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
3722 f_next_gp = TYPE_FIELDS (va_list_type_node);
3723 f_next_gp_limit = TREE_CHAIN (f_next_gp);
3724 f_next_cop = TREE_CHAIN (f_next_gp_limit);
3725 f_next_stack = TREE_CHAIN (f_next_cop);
3727 next_gp = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp), valist, f_next_gp,
3729 next_gp_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp_limit),
3730 valist, f_next_gp_limit, NULL_TREE);
3731 next_cop = build3 (COMPONENT_REF, TREE_TYPE (f_next_cop), valist, f_next_cop,
3733 next_stack = build3 (COMPONENT_REF, TREE_TYPE (f_next_stack),
3734 valist, f_next_stack, NULL_TREE);
3736 /* if f_next_gp < f_next_gp_limit
3737 IF (VECTOR_P && IVC2)
3745 val = *f_next_stack;
3746 f_next_stack += rsize;
3750 label_sover = create_artificial_label (UNKNOWN_LOCATION);
3751 label_selse = create_artificial_label (UNKNOWN_LOCATION);
3752 res_addr = create_tmp_var (ptr_type_node, NULL);
3754 tmp = build2 (GE_EXPR, boolean_type_node, next_gp,
3755 unshare_expr (next_gp_limit));
3756 tmp = build3 (COND_EXPR, void_type_node, tmp,
3757 build1 (GOTO_EXPR, void_type_node,
3758 unshare_expr (label_selse)),
3760 gimplify_and_add (tmp, pre_p);
3764 tmp = build2 (MODIFY_EXPR, void_type_node, res_addr, next_cop);
3765 gimplify_and_add (tmp, pre_p);
3769 tmp = build2 (MODIFY_EXPR, void_type_node, res_addr, next_gp);
3770 gimplify_and_add (tmp, pre_p);
3773 tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node,
3774 unshare_expr (next_gp), size_int (4));
3775 gimplify_assign (unshare_expr (next_gp), tmp, pre_p);
3777 tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node,
3778 unshare_expr (next_cop), size_int (8));
3779 gimplify_assign (unshare_expr (next_cop), tmp, pre_p);
3781 tmp = build1 (GOTO_EXPR, void_type_node, unshare_expr (label_sover));
3782 gimplify_and_add (tmp, pre_p);
3786 tmp = build1 (LABEL_EXPR, void_type_node, unshare_expr (label_selse));
3787 gimplify_and_add (tmp, pre_p);
3789 tmp = build2 (MODIFY_EXPR, void_type_node, res_addr, unshare_expr (next_stack));
3790 gimplify_and_add (tmp, pre_p);
3792 tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node,
3793 unshare_expr (next_stack), size_int (rsize));
3794 gimplify_assign (unshare_expr (next_stack), tmp, pre_p);
3798 tmp = build1 (LABEL_EXPR, void_type_node, unshare_expr (label_sover));
3799 gimplify_and_add (tmp, pre_p);
3801 res_addr = fold_convert (build_pointer_type (type), res_addr);
3804 res_addr = build_va_arg_indirect_ref (res_addr);
3806 return build_va_arg_indirect_ref (res_addr);
3810 mep_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
3811 rtx libname ATTRIBUTE_UNUSED,
3812 tree fndecl ATTRIBUTE_UNUSED)
3816 if (fntype && lookup_attribute ("vliw", TYPE_ATTRIBUTES (fntype)))
3823 mep_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode,
3824 tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
3826 /* VOIDmode is a signal for the backend to pass data to the call
3827 expander via the second operand to the call pattern. We use
3828 this to determine whether to use "jsr" or "jsrv". */
3829 if (mode == VOIDmode)
3830 return GEN_INT (cum.vliw);
3832 /* If we havn't run out of argument registers, return the next. */
3835 if (type && TARGET_IVC2 && VECTOR_TYPE_P (type))
3836 return gen_rtx_REG (mode, cum.nregs + 49);
3838 return gen_rtx_REG (mode, cum.nregs + 1);
3841 /* Otherwise the argument goes on the stack. */
3846 mep_pass_by_reference (CUMULATIVE_ARGS * cum ATTRIBUTE_UNUSED,
3847 enum machine_mode mode,
3849 bool named ATTRIBUTE_UNUSED)
3851 int size = bytesize (type, mode);
3853 /* This is non-obvious, but yes, large values passed after we've run
3854 out of registers are *still* passed by reference - we put the
3855 address of the parameter on the stack, as well as putting the
3856 parameter itself elsewhere on the stack. */
3858 if (size <= 0 || size > 8)
3862 if (TARGET_IVC2 && cum->nregs < 4 && type != NULL_TREE && VECTOR_TYPE_P (type))
3868 mep_arg_advance (CUMULATIVE_ARGS *pcum,
3869 enum machine_mode mode ATTRIBUTE_UNUSED,
3870 tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
3876 mep_return_in_memory (const_tree type, const_tree decl ATTRIBUTE_UNUSED)
3878 int size = bytesize (type, BLKmode);
3879 if (TARGET_IVC2 && VECTOR_TYPE_P (type))
3880 return size > 0 && size <= 8 ? 0 : 1;
3881 return size > 0 && size <= 4 ? 0 : 1;
3885 mep_narrow_volatile_bitfield (void)
3891 /* Implement FUNCTION_VALUE. All values are returned in $0. */
3894 mep_function_value (tree type, tree func ATTRIBUTE_UNUSED)
3896 if (TARGET_IVC2 && VECTOR_TYPE_P (type))
3897 return gen_rtx_REG (TYPE_MODE (type), 48);
3898 return gen_rtx_REG (TYPE_MODE (type), RETURN_VALUE_REGNUM);
3901 /* Implement LIBCALL_VALUE, using the same rules as mep_function_value. */
3904 mep_libcall_value (enum machine_mode mode)
3906 return gen_rtx_REG (mode, RETURN_VALUE_REGNUM);
3909 /* Handle pipeline hazards. */
3911 typedef enum { op_none, op_stc, op_fsft, op_ret } op_num;
3912 static const char *opnames[] = { "", "stc", "fsft", "ret" };
3914 static int prev_opcode = 0;
3916 /* This isn't as optimal as it could be, because we don't know what
3917 control register the STC opcode is storing in. We only need to add
3918 the nop if it's the relevent register, but we add it for irrelevent
3922 mep_asm_output_opcode (FILE *file, const char *ptr)
3924 int this_opcode = op_none;
3925 const char *hazard = 0;
3930 if (strncmp (ptr, "fsft", 4) == 0 && !ISGRAPH (ptr[4]))
3931 this_opcode = op_fsft;
3934 if (strncmp (ptr, "ret", 3) == 0 && !ISGRAPH (ptr[3]))
3935 this_opcode = op_ret;
3938 if (strncmp (ptr, "stc", 3) == 0 && !ISGRAPH (ptr[3]))
3939 this_opcode = op_stc;
3943 if (prev_opcode == op_stc && this_opcode == op_fsft)
3945 if (prev_opcode == op_stc && this_opcode == op_ret)
3949 fprintf(file, "%s\t# %s-%s hazard\n\t",
3950 hazard, opnames[prev_opcode], opnames[this_opcode]);
3952 prev_opcode = this_opcode;
3955 /* Handle attributes. */
3958 mep_validate_based_tiny (tree *node, tree name, tree args,
3959 int flags ATTRIBUTE_UNUSED, bool *no_add)
3961 if (TREE_CODE (*node) != VAR_DECL
3962 && TREE_CODE (*node) != POINTER_TYPE
3963 && TREE_CODE (*node) != TYPE_DECL)
3965 warning (0, "%qE attribute only applies to variables", name);
3968 else if (args == NULL_TREE && TREE_CODE (*node) == VAR_DECL)
3970 if (! (TREE_PUBLIC (*node) || TREE_STATIC (*node)))
3972 warning (0, "address region attributes not allowed with auto storage class");
3975 /* Ignore storage attribute of pointed to variable: char __far * x; */
3976 if (TREE_TYPE (*node) && TREE_CODE (TREE_TYPE (*node)) == POINTER_TYPE)
3978 warning (0, "address region attributes on pointed-to types ignored");
3987 mep_multiple_address_regions (tree list, bool check_section_attr)
3990 int count_sections = 0;
3991 int section_attr_count = 0;
3993 for (a = list; a; a = TREE_CHAIN (a))
3995 if (is_attribute_p ("based", TREE_PURPOSE (a))
3996 || is_attribute_p ("tiny", TREE_PURPOSE (a))
3997 || is_attribute_p ("near", TREE_PURPOSE (a))
3998 || is_attribute_p ("far", TREE_PURPOSE (a))
3999 || is_attribute_p ("io", TREE_PURPOSE (a)))
4001 if (check_section_attr)
4002 section_attr_count += is_attribute_p ("section", TREE_PURPOSE (a));
4005 if (check_section_attr)
4006 return section_attr_count;
4008 return count_sections;
4011 #define MEP_ATTRIBUTES(decl) \
4012 (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \
4013 : DECL_ATTRIBUTES (decl) \
4014 ? (DECL_ATTRIBUTES (decl)) \
4015 : TYPE_ATTRIBUTES (TREE_TYPE (decl))
4018 mep_validate_near_far (tree *node, tree name, tree args,
4019 int flags ATTRIBUTE_UNUSED, bool *no_add)
4021 if (TREE_CODE (*node) != VAR_DECL
4022 && TREE_CODE (*node) != FUNCTION_DECL
4023 && TREE_CODE (*node) != METHOD_TYPE
4024 && TREE_CODE (*node) != POINTER_TYPE
4025 && TREE_CODE (*node) != TYPE_DECL)
4027 warning (0, "%qE attribute only applies to variables and functions",
4031 else if (args == NULL_TREE && TREE_CODE (*node) == VAR_DECL)
4033 if (! (TREE_PUBLIC (*node) || TREE_STATIC (*node)))
4035 warning (0, "address region attributes not allowed with auto storage class");
4038 /* Ignore storage attribute of pointed to variable: char __far * x; */
4039 if (TREE_TYPE (*node) && TREE_CODE (TREE_TYPE (*node)) == POINTER_TYPE)
4041 warning (0, "address region attributes on pointed-to types ignored");
4045 else if (mep_multiple_address_regions (MEP_ATTRIBUTES (*node), false) > 0)
4047 warning (0, "duplicate address region attribute %qE in declaration of %qE on line %d",
4048 name, DECL_NAME (*node), DECL_SOURCE_LINE (*node));
4049 DECL_ATTRIBUTES (*node) = NULL_TREE;
4055 mep_validate_disinterrupt (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
4056 int flags ATTRIBUTE_UNUSED, bool *no_add)
4058 if (TREE_CODE (*node) != FUNCTION_DECL
4059 && TREE_CODE (*node) != METHOD_TYPE)
4061 warning (0, "%qE attribute only applies to functions", name);
4068 mep_validate_interrupt (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
4069 int flags ATTRIBUTE_UNUSED, bool *no_add)
4073 if (TREE_CODE (*node) != FUNCTION_DECL)
4075 warning (0, "%qE attribute only applies to functions", name);
4080 if (DECL_DECLARED_INLINE_P (*node))
4081 error ("cannot inline interrupt function %qE", DECL_NAME (*node));
4082 DECL_UNINLINABLE (*node) = 1;
4084 function_type = TREE_TYPE (*node);
4086 if (TREE_TYPE (function_type) != void_type_node)
4087 error ("interrupt function must have return type of void");
4089 if (TYPE_ARG_TYPES (function_type)
4090 && (TREE_VALUE (TYPE_ARG_TYPES (function_type)) != void_type_node
4091 || TREE_CHAIN (TYPE_ARG_TYPES (function_type)) != NULL_TREE))
4092 error ("interrupt function must have no arguments");
4098 mep_validate_io_cb (tree *node, tree name, tree args,
4099 int flags ATTRIBUTE_UNUSED, bool *no_add)
4101 if (TREE_CODE (*node) != VAR_DECL)
4103 warning (0, "%qE attribute only applies to variables", name);
4107 if (args != NULL_TREE)
4109 if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
4110 TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
4111 if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
4113 warning (0, "%qE attribute allows only an integer constant argument",
4119 if (*no_add == false && !TARGET_IO_NO_VOLATILE)
4120 TREE_THIS_VOLATILE (*node) = 1;
4126 mep_validate_vliw (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
4127 int flags ATTRIBUTE_UNUSED, bool *no_add)
4129 if (TREE_CODE (*node) != FUNCTION_TYPE
4130 && TREE_CODE (*node) != FUNCTION_DECL
4131 && TREE_CODE (*node) != METHOD_TYPE
4132 && TREE_CODE (*node) != FIELD_DECL
4133 && TREE_CODE (*node) != TYPE_DECL)
4135 static int gave_pointer_note = 0;
4136 static int gave_array_note = 0;
4137 static const char * given_type = NULL;
4139 given_type = tree_code_name[TREE_CODE (*node)];
4140 if (TREE_CODE (*node) == POINTER_TYPE)
4141 given_type = "pointers";
4142 if (TREE_CODE (*node) == ARRAY_TYPE)
4143 given_type = "arrays";
4146 warning (0, "%qE attribute only applies to functions, not %s",
4149 warning (0, "%qE attribute only applies to functions",
4153 if (TREE_CODE (*node) == POINTER_TYPE
4154 && !gave_pointer_note)
4156 inform (input_location, "To describe a pointer to a VLIW function, use syntax like this:");
4157 inform (input_location, " typedef int (__vliw *vfuncptr) ();");
4158 gave_pointer_note = 1;
4161 if (TREE_CODE (*node) == ARRAY_TYPE
4162 && !gave_array_note)
4164 inform (input_location, "To describe an array of VLIW function pointers, use syntax like this:");
4165 inform (input_location, " typedef int (__vliw *vfuncptr[]) ();");
4166 gave_array_note = 1;
4170 error ("VLIW functions are not allowed without a VLIW configuration");
4174 static const struct attribute_spec mep_attribute_table[11] =
4176 /* name min max decl type func handler */
4177 { "based", 0, 0, false, false, false, mep_validate_based_tiny },
4178 { "tiny", 0, 0, false, false, false, mep_validate_based_tiny },
4179 { "near", 0, 0, false, false, false, mep_validate_near_far },
4180 { "far", 0, 0, false, false, false, mep_validate_near_far },
4181 { "disinterrupt", 0, 0, false, false, false, mep_validate_disinterrupt },
4182 { "interrupt", 0, 0, false, false, false, mep_validate_interrupt },
4183 { "io", 0, 1, false, false, false, mep_validate_io_cb },
4184 { "cb", 0, 1, false, false, false, mep_validate_io_cb },
4185 { "vliw", 0, 0, false, true, false, mep_validate_vliw },
4186 { NULL, 0, 0, false, false, false, NULL }
4190 mep_function_attribute_inlinable_p (const_tree callee)
4192 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (callee));
4193 if (!attrs) attrs = DECL_ATTRIBUTES (callee);
4194 return (lookup_attribute ("disinterrupt", attrs) == 0
4195 && lookup_attribute ("interrupt", attrs) == 0);
4199 mep_can_inline_p (tree caller, tree callee)
4201 if (TREE_CODE (callee) == ADDR_EXPR)
4202 callee = TREE_OPERAND (callee, 0);
4204 if (!mep_vliw_function_p (caller)
4205 && mep_vliw_function_p (callee))
4213 #define FUNC_DISINTERRUPT 2
4216 struct GTY(()) pragma_entry {
4219 const char *funcname;
4221 typedef struct pragma_entry pragma_entry;