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;
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);
2870 really_need_stack_frame = frame_size;
2872 really_need_stack_frame |= mep_assign_save_slots (reg_save_size);
2874 sp_offset = reg_save_size;
2875 if (sp_offset + frame_size < 128)
2876 sp_offset += frame_size ;
2878 add_constant (SP_REGNO, SP_REGNO, -sp_offset, 1);
2880 for (i=0; i<FIRST_PSEUDO_REGISTER; i++)
2881 if (mep_call_saves_register(i))
2885 enum machine_mode rmode;
2887 rss = cfun->machine->reg_save_slot[i];
2889 if ((i == TP_REGNO || i == GP_REGNO || i == LP_REGNO)
2890 && (!mep_reg_set_in_function (i)
2891 && !mep_interrupt_p ()))
2894 if (mep_reg_size (i) == 8)
2899 /* If there is a pseudo associated with this register's initial value,
2900 reload might have already spilt it to the stack slot suggested by
2901 ALLOCATE_INITIAL_VALUE. The moves emitted here can then be safely
2903 mem = gen_rtx_MEM (rmode,
2904 plus_constant (stack_pointer_rtx, sp_offset - rss));
2905 maybe_dead_p = rtx_equal_p (mem, has_hard_reg_initial_val (rmode, i));
2907 if (GR_REGNO_P (i) || LOADABLE_CR_REGNO_P (i))
2908 F(maybe_dead_move (mem, gen_rtx_REG (rmode, i), maybe_dead_p));
2909 else if (rmode == DImode)
2912 int be = TARGET_BIG_ENDIAN ? 4 : 0;
2914 mem = gen_rtx_MEM (SImode,
2915 plus_constant (stack_pointer_rtx, sp_offset - rss + be));
2917 maybe_dead_move (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2918 gen_rtx_REG (SImode, i),
2920 maybe_dead_move (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP+1),
2921 gen_rtx_ZERO_EXTRACT (SImode,
2922 gen_rtx_REG (DImode, i),
2926 insn = maybe_dead_move (mem,
2927 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2929 RTX_FRAME_RELATED_P (insn) = 1;
2931 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2932 gen_rtx_SET (VOIDmode,
2934 gen_rtx_REG (rmode, i)));
2935 mem = gen_rtx_MEM (SImode,
2936 plus_constant (stack_pointer_rtx, sp_offset - rss + (4-be)));
2937 insn = maybe_dead_move (mem,
2938 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP+1),
2944 maybe_dead_move (gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
2945 gen_rtx_REG (rmode, i),
2947 insn = maybe_dead_move (mem,
2948 gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
2950 RTX_FRAME_RELATED_P (insn) = 1;
2952 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2953 gen_rtx_SET (VOIDmode,
2955 gen_rtx_REG (rmode, i)));
2959 if (frame_pointer_needed)
2961 /* We've already adjusted down by sp_offset. Total $sp change
2962 is reg_save_size + frame_size. We want a net change here of
2963 just reg_save_size. */
2964 add_constant (FP_REGNO, SP_REGNO, sp_offset - reg_save_size, 1);
2967 add_constant (SP_REGNO, SP_REGNO, sp_offset-(reg_save_size+frame_size), 1);
2969 if (mep_interrupt_p ())
2971 mep_reload_pointer(GP_REGNO, "__sdabase");
2972 mep_reload_pointer(TP_REGNO, "__tpbase");
2977 mep_start_function (FILE *file, HOST_WIDE_INT hwi_local)
2979 int local = hwi_local;
2980 int frame_size = local + crtl->outgoing_args_size;
2985 int slot_map[FIRST_PSEUDO_REGISTER], si, sj;
2987 reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
2988 frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
2989 sp_offset = reg_save_size + frame_size;
2991 ffill = cfun->machine->frame_filler;
2993 if (cfun->machine->mep_frame_pointer_needed)
2994 reg_names[FP_REGNO] = "$fp";
2996 reg_names[FP_REGNO] = "$8";
3001 if (debug_info_level == DINFO_LEVEL_NONE)
3003 fprintf (file, "\t# frame: %d", sp_offset);
3005 fprintf (file, " %d regs", reg_save_size);
3007 fprintf (file, " %d locals", local);
3008 if (crtl->outgoing_args_size)
3009 fprintf (file, " %d args", crtl->outgoing_args_size);
3010 fprintf (file, "\n");
3014 fprintf (file, "\t#\n");
3015 fprintf (file, "\t# Initial Frame Information:\n");
3016 if (sp_offset || !frame_pointer_needed)
3017 fprintf (file, "\t# Entry ---------- 0\n");
3019 /* Sort registers by save slots, so they're printed in the order
3020 they appear in memory, not the order they're saved in. */
3021 for (si=0; si<FIRST_PSEUDO_REGISTER; si++)
3023 for (si=0; si<FIRST_PSEUDO_REGISTER-1; si++)
3024 for (sj=si+1; sj<FIRST_PSEUDO_REGISTER; sj++)
3025 if (cfun->machine->reg_save_slot[slot_map[si]]
3026 > cfun->machine->reg_save_slot[slot_map[sj]])
3028 int t = slot_map[si];
3029 slot_map[si] = slot_map[sj];
3034 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3037 int r = slot_map[i];
3038 int rss = cfun->machine->reg_save_slot[r];
3040 if (!mep_call_saves_register (r))
3043 if ((r == TP_REGNO || r == GP_REGNO || r == LP_REGNO)
3044 && (!mep_reg_set_in_function (r)
3045 && !mep_interrupt_p ()))
3048 rsize = mep_reg_size(r);
3049 skip = rss - (sp+rsize);
3051 fprintf (file, "\t# %3d bytes for alignment\n", skip);
3052 fprintf (file, "\t# %3d bytes for saved %-3s %3d($sp)\n",
3053 rsize, reg_names[r], sp_offset - rss);
3057 skip = reg_save_size - sp;
3059 fprintf (file, "\t# %3d bytes for alignment\n", skip);
3061 if (frame_pointer_needed)
3062 fprintf (file, "\t# FP ---> ---------- %d (sp-%d)\n", reg_save_size, sp_offset-reg_save_size);
3064 fprintf (file, "\t# %3d bytes for local vars\n", local);
3066 fprintf (file, "\t# %3d bytes for alignment\n", ffill);
3067 if (crtl->outgoing_args_size)
3068 fprintf (file, "\t# %3d bytes for outgoing args\n",
3069 crtl->outgoing_args_size);
3070 fprintf (file, "\t# SP ---> ---------- %d\n", sp_offset);
3071 fprintf (file, "\t#\n");
3075 static int mep_prevent_lp_restore = 0;
3076 static int mep_sibcall_epilogue = 0;
3079 mep_expand_epilogue (void)
3081 int i, sp_offset = 0;
3082 int reg_save_size = 0;
3084 int lp_temp = LP_REGNO, lp_slot = -1;
3085 int really_need_stack_frame = get_frame_size() + crtl->outgoing_args_size;
3086 int interrupt_handler = mep_interrupt_p ();
3088 if (profile_arc_flag == 2)
3089 emit_insn (gen_mep_bb_trace_ret ());
3091 reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
3092 frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
3094 really_need_stack_frame |= mep_assign_save_slots (reg_save_size);
3096 if (frame_pointer_needed)
3098 /* If we have a frame pointer, we won't have a reliable stack
3099 pointer (alloca, you know), so rebase SP from FP */
3100 emit_move_insn (gen_rtx_REG (SImode, SP_REGNO),
3101 gen_rtx_REG (SImode, FP_REGNO));
3102 sp_offset = reg_save_size;
3106 /* SP is right under our local variable space. Adjust it if
3108 sp_offset = reg_save_size + frame_size;
3109 if (sp_offset >= 128)
3111 add_constant (SP_REGNO, SP_REGNO, frame_size, 0);
3112 sp_offset -= frame_size;
3116 /* This is backwards so that we restore the control and coprocessor
3117 registers before the temporary registers we use to restore
3119 for (i=FIRST_PSEUDO_REGISTER-1; i>=1; i--)
3120 if (mep_call_saves_register (i))
3122 enum machine_mode rmode;
3123 int rss = cfun->machine->reg_save_slot[i];
3125 if (mep_reg_size (i) == 8)
3130 if ((i == TP_REGNO || i == GP_REGNO || i == LP_REGNO)
3131 && !(mep_reg_set_in_function (i) || interrupt_handler))
3133 if (mep_prevent_lp_restore && i == LP_REGNO)
3135 if (!mep_prevent_lp_restore
3136 && !interrupt_handler
3137 && (i == 10 || i == 11))
3140 if (GR_REGNO_P (i) || LOADABLE_CR_REGNO_P (i))
3141 emit_move_insn (gen_rtx_REG (rmode, i),
3143 plus_constant (stack_pointer_rtx,
3147 if (i == LP_REGNO && !mep_sibcall_epilogue && !interrupt_handler)
3148 /* Defer this one so we can jump indirect rather than
3149 copying the RA to $lp and "ret". EH epilogues
3150 automatically skip this anyway. */
3151 lp_slot = sp_offset-rss;
3154 emit_move_insn (gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
3156 plus_constant (stack_pointer_rtx,
3158 emit_move_insn (gen_rtx_REG (rmode, i),
3159 gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP));
3165 /* Restore this one last so we know it will be in the temp
3166 register when we return by jumping indirectly via the temp. */
3167 emit_move_insn (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
3168 gen_rtx_MEM (SImode,
3169 plus_constant (stack_pointer_rtx,
3171 lp_temp = REGSAVE_CONTROL_TEMP;
3175 add_constant (SP_REGNO, SP_REGNO, sp_offset, 0);
3177 if (crtl->calls_eh_return && mep_prevent_lp_restore)
3178 emit_insn (gen_addsi3 (gen_rtx_REG (SImode, SP_REGNO),
3179 gen_rtx_REG (SImode, SP_REGNO),
3180 cfun->machine->eh_stack_adjust));
3182 if (mep_sibcall_epilogue)
3185 if (mep_disinterrupt_p ())
3186 emit_insn (gen_mep_enable_int ());
3188 if (mep_prevent_lp_restore)
3190 emit_jump_insn (gen_eh_return_internal ());
3193 else if (interrupt_handler)
3194 emit_jump_insn (gen_mep_reti ());
3196 emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode, lp_temp)));
3200 mep_expand_eh_return (rtx *operands)
3202 if (GET_CODE (operands[0]) != REG || REGNO (operands[0]) != LP_REGNO)
3204 rtx ra = gen_rtx_REG (Pmode, LP_REGNO);
3205 emit_move_insn (ra, operands[0]);
3209 emit_insn (gen_eh_epilogue (operands[0]));
3213 mep_emit_eh_epilogue (rtx *operands ATTRIBUTE_UNUSED)
3215 cfun->machine->eh_stack_adjust = gen_rtx_REG (Pmode, 0);
3216 mep_prevent_lp_restore = 1;
3217 mep_expand_epilogue ();
3218 mep_prevent_lp_restore = 0;
3222 mep_expand_sibcall_epilogue (void)
3224 mep_sibcall_epilogue = 1;
3225 mep_expand_epilogue ();
3226 mep_sibcall_epilogue = 0;
3230 mep_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
3235 if (mep_section_tag (DECL_RTL (decl)) == 'f')
3238 /* Can't call to a sibcall from an interrupt or disinterrupt function. */
3239 if (mep_interrupt_p () || mep_disinterrupt_p ())
3246 mep_return_stackadj_rtx (void)
3248 return gen_rtx_REG (SImode, 10);
3252 mep_return_handler_rtx (void)
3254 return gen_rtx_REG (SImode, LP_REGNO);
3258 mep_function_profiler (FILE *file)
3260 /* Always right at the beginning of the function. */
3261 fprintf (file, "\t# mep function profiler\n");
3262 fprintf (file, "\tadd\t$sp, -8\n");
3263 fprintf (file, "\tsw\t$0, ($sp)\n");
3264 fprintf (file, "\tldc\t$0, $lp\n");
3265 fprintf (file, "\tsw\t$0, 4($sp)\n");
3266 fprintf (file, "\tbsr\t__mep_mcount\n");
3267 fprintf (file, "\tlw\t$0, 4($sp)\n");
3268 fprintf (file, "\tstc\t$0, $lp\n");
3269 fprintf (file, "\tlw\t$0, ($sp)\n");
3270 fprintf (file, "\tadd\t$sp, 8\n\n");
3274 mep_emit_bb_trace_ret (void)
3276 fprintf (asm_out_file, "\t# end of block profiling\n");
3277 fprintf (asm_out_file, "\tadd\t$sp, -8\n");
3278 fprintf (asm_out_file, "\tsw\t$0, ($sp)\n");
3279 fprintf (asm_out_file, "\tldc\t$0, $lp\n");
3280 fprintf (asm_out_file, "\tsw\t$0, 4($sp)\n");
3281 fprintf (asm_out_file, "\tbsr\t__bb_trace_ret\n");
3282 fprintf (asm_out_file, "\tlw\t$0, 4($sp)\n");
3283 fprintf (asm_out_file, "\tstc\t$0, $lp\n");
3284 fprintf (asm_out_file, "\tlw\t$0, ($sp)\n");
3285 fprintf (asm_out_file, "\tadd\t$sp, 8\n\n");
3292 /* Operand Printing. */
3295 mep_print_operand_address (FILE *stream, rtx address)
3297 if (GET_CODE (address) == MEM)
3298 address = XEXP (address, 0);
3300 /* cf: gcc.dg/asm-4.c. */
3301 gcc_assert (GET_CODE (address) == REG);
3303 mep_print_operand (stream, address, 0);
3309 const char *pattern;
3312 const conversions[] =
3315 { 0, "m+ri", "3(2)" },
3319 { 0, "mLrs", "%lo(3)(2)" },
3320 { 0, "mLr+si", "%lo(4+5)(2)" },
3321 { 0, "m+ru2s", "%tpoff(5)(2)" },
3322 { 0, "m+ru3s", "%sdaoff(5)(2)" },
3323 { 0, "m+r+u2si", "%tpoff(6+7)(2)" },
3324 { 0, "m+ru2+si", "%tpoff(6+7)(2)" },
3325 { 0, "m+r+u3si", "%sdaoff(6+7)(2)" },
3326 { 0, "m+ru3+si", "%sdaoff(6+7)(2)" },
3328 { 0, "m+si", "(2+3)" },
3329 { 0, "m+li", "(2+3)" },
3332 { 0, "+si", "1+2" },
3333 { 0, "+u2si", "%tpoff(3+4)" },
3334 { 0, "+u3si", "%sdaoff(3+4)" },
3340 { 'h', "Hs", "%hi(1)" },
3342 { 'I', "u2s", "%tpoff(2)" },
3343 { 'I', "u3s", "%sdaoff(2)" },
3344 { 'I', "+u2si", "%tpoff(3+4)" },
3345 { 'I', "+u3si", "%sdaoff(3+4)" },
3347 { 'P', "mr", "(1\\+),\\0" },
3353 unique_bit_in (HOST_WIDE_INT i)
3357 case 0x01: case 0xfe: return 0;
3358 case 0x02: case 0xfd: return 1;
3359 case 0x04: case 0xfb: return 2;
3360 case 0x08: case 0xf7: return 3;
3361 case 0x10: case 0x7f: return 4;
3362 case 0x20: case 0xbf: return 5;
3363 case 0x40: case 0xdf: return 6;
3364 case 0x80: case 0xef: return 7;
3371 bit_size_for_clip (HOST_WIDE_INT i)
3375 for (rv = 0; rv < 31; rv ++)
3376 if (((HOST_WIDE_INT) 1 << rv) > i)
3381 /* Print an operand to a assembler instruction. */
3384 mep_print_operand (FILE *file, rtx x, int code)
3387 const char *real_name;
3391 /* Print a mnemonic to do CR <- CR moves. Find out which intrinsic
3392 we're using, then skip over the "mep_" part of its name. */
3393 const struct cgen_insn *insn;
3395 if (mep_get_move_insn (mep_cmov, &insn))
3396 fputs (cgen_intrinsics[insn->intrinsic] + 4, file);
3398 mep_intrinsic_unavailable (mep_cmov);
3403 switch (GET_CODE (x))
3406 fputs ("clr", file);
3409 fputs ("set", file);
3412 fputs ("not", file);
3415 output_operand_lossage ("invalid %%L code");
3420 /* Print the second operand of a CR <- CR move. If we're using
3421 a two-operand instruction (i.e., a real cmov), then just print
3422 the operand normally. If we're using a "reg, reg, immediate"
3423 instruction such as caddi3, print the operand followed by a
3424 zero field. If we're using a three-register instruction,
3425 print the operand twice. */
3426 const struct cgen_insn *insn;
3428 mep_print_operand (file, x, 0);
3429 if (mep_get_move_insn (mep_cmov, &insn)
3430 && insn_data[insn->icode].n_operands == 3)
3433 if (insn_data[insn->icode].operand[2].predicate (x, VOIDmode))
3434 mep_print_operand (file, x, 0);
3436 mep_print_operand (file, const0_rtx, 0);
3442 for (i = 0; conversions[i].pattern; i++)
3443 if (conversions[i].code == code
3444 && strcmp(conversions[i].pattern, pattern) == 0)
3446 for (j = 0; conversions[i].format[j]; j++)
3447 if (conversions[i].format[j] == '\\')
3449 fputc (conversions[i].format[j+1], file);
3452 else if (ISDIGIT(conversions[i].format[j]))
3454 rtx r = patternr[conversions[i].format[j] - '0'];
3455 switch (GET_CODE (r))
3458 fprintf (file, "%s", reg_names [REGNO (r)]);
3464 fprintf (file, "%d", unique_bit_in (INTVAL (r)));
3467 fprintf (file, "%d", bit_size_for_clip (INTVAL (r)));
3470 fprintf (file, "0x%x", ((int) INTVAL (r) >> 16) & 0xffff);
3473 fprintf (file, "%d", bit_size_for_clip (INTVAL (r)) - 1);
3476 fprintf (file, "0x%x", (int) INTVAL (r) & 0xffff);
3479 if (INTVAL (r) & ~(HOST_WIDE_INT)0xff
3480 && !(INTVAL (r) & 0xff))
3481 fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL(r));
3483 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3486 if (INTVAL (r) & ~(HOST_WIDE_INT)0xff
3487 && conversions[i].format[j+1] == 0)
3489 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (r));
3490 fprintf (file, " # 0x%x", (int) INTVAL(r) & 0xffff);
3493 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3496 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3501 fprintf(file, "[const_double 0x%lx]",
3502 (unsigned long) CONST_DOUBLE_HIGH(r));
3505 real_name = TARGET_STRIP_NAME_ENCODING (XSTR (r, 0));
3506 assemble_name (file, real_name);
3509 output_asm_label (r);
3512 fprintf (stderr, "don't know how to print this operand:");
3519 if (conversions[i].format[j] == '+'
3520 && (!code || code == 'I')
3521 && ISDIGIT (conversions[i].format[j+1])
3522 && GET_CODE (patternr[conversions[i].format[j+1] - '0']) == CONST_INT
3523 && INTVAL (patternr[conversions[i].format[j+1] - '0']) < 0)
3525 fputc(conversions[i].format[j], file);
3529 if (!conversions[i].pattern)
3531 error ("unconvertible operand %c %qs", code?code:'-', pattern);
3539 mep_final_prescan_insn (rtx insn, rtx *operands ATTRIBUTE_UNUSED,
3540 int noperands ATTRIBUTE_UNUSED)
3542 /* Despite the fact that MeP is perfectly capable of branching and
3543 doing something else in the same bundle, gcc does jump
3544 optimization *after* scheduling, so we cannot trust the bundling
3545 flags on jump instructions. */
3546 if (GET_MODE (insn) == BImode
3547 && get_attr_slots (insn) != SLOTS_CORE)
3548 fputc ('+', asm_out_file);
3551 /* Function args in registers. */
3554 mep_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
3555 enum machine_mode mode ATTRIBUTE_UNUSED,
3556 tree type ATTRIBUTE_UNUSED, int *pretend_size,
3557 int second_time ATTRIBUTE_UNUSED)
3559 int nsave = 4 - (cum->nregs + 1);
3562 cfun->machine->arg_regs_to_save = nsave;
3563 *pretend_size = nsave * 4;
3567 bytesize (const_tree type, enum machine_mode mode)
3569 if (mode == BLKmode)
3570 return int_size_in_bytes (type);
3571 return GET_MODE_SIZE (mode);
3575 mep_expand_builtin_saveregs (void)
3580 ns = cfun->machine->arg_regs_to_save;