1 /* Output routines for Visium.
2 Copyright (C) 2002-2016 Free Software Foundation, Inc.
3 Contributed by C.Nettleton, J.P.Parkes and P.Garbett.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
28 #include "gimple-expr.h"
31 #include "stringpool.h"
37 #include "diagnostic-core.h"
40 #include "fold-const.h"
41 #include "stor-layout.h"
45 #include "insn-attr.h"
49 #include "langhooks.h"
51 #include "tm-constrs.h"
53 #include "tree-pass.h"
57 /* This file should be included last. */
58 #include "target-def.h"
60 /* Enumeration of indexes into machine_libfunc_table. */
61 enum machine_libfunc_index
71 MLTI_set_trampoline_parity
,
76 struct GTY(()) machine_libfuncs
81 /* The table of Visium-specific libfuncs. */
82 static GTY(()) struct machine_libfuncs visium_libfuncs
;
84 #define vlt visium_libfuncs.table
86 /* Accessor macros for visium_libfuncs. */
87 #define long_int_memcpy_libfunc (vlt[MLTI_long_int_memcpy])
88 #define wrd_memcpy_libfunc (vlt[MLTI_wrd_memcpy])
89 #define byt_memcpy_libfunc (vlt[MLTI_byt_memcpy])
90 #define long_int_memset_libfunc (vlt[MLTI_long_int_memset])
91 #define wrd_memset_libfunc (vlt[MLTI_wrd_memset])
92 #define byt_memset_libfunc (vlt[MLTI_byt_memset])
93 #define set_trampoline_parity_libfunc (vlt[MLTI_set_trampoline_parity])
95 /* Machine specific function data. */
96 struct GTY (()) machine_function
98 /* Size of the frame of the function. */
101 /* Size of the reg parm save area, non-zero only for functions with variable
102 argument list. We cannot use the crtl->args.pretend_args_size machinery
103 for this purpose because this size is added to virtual_incoming_args_rtx
104 to give the location of the first parameter passed by the caller on the
105 stack and virtual_incoming_args_rtx is also the location of the first
106 parameter on the stack. So crtl->args.pretend_args_size can be non-zero
107 only if the first non-register named parameter is not passed entirely on
108 the stack and this runs afoul of the need to have a reg parm save area
109 even with a variable argument list starting on the stack because of the
110 separate handling of general and floating-point registers. */
111 int reg_parm_save_area_size
;
113 /* True if we have created an rtx which relies on the frame pointer. */
116 /* True if we have exposed the flags register. From this moment on, we
117 cannot generate simple operations for integer registers. We could
118 use reload_completed for this purpose, but this would cripple the
119 postreload CSE and GCSE passes which run before postreload split. */
123 #define visium_frame_size cfun->machine->frame_size
124 #define visium_reg_parm_save_area_size cfun->machine->reg_parm_save_area_size
125 #define visium_frame_needed cfun->machine->frame_needed
126 #define visium_flags_exposed cfun->machine->flags_exposed
128 /* 1 if the next opcode is to be specially indented. */
129 int visium_indent_opcode
= 0;
131 /* Register number used for long branches when LR isn't available. It
132 must be a call-used register since it isn't saved on function entry.
133 We do not care whether the branch is predicted or not on the GR6,
134 given how unlikely it is to have a long branch in a leaf function. */
135 static unsigned int long_branch_regnum
= 31;
137 static tree
visium_handle_interrupt_attr (tree
*, tree
, tree
, int, bool *);
138 static inline bool current_function_saves_fp (void);
139 static inline bool current_function_saves_lr (void);
140 static inline bool current_function_has_lr_slot (void);
142 /* Supported attributes:
143 interrupt -- specifies this function is an interrupt handler. */
144 static const struct attribute_spec visium_attribute_table
[] =
146 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
147 affects_type_identity } */
148 {"interrupt", 0, 0, true, false, false, visium_handle_interrupt_attr
, false},
149 {NULL
, 0, 0, false, false, false, NULL
, false}
152 static struct machine_function
*visium_init_machine_status (void);
154 /* Target hooks and TARGET_INITIALIZER */
156 static bool visium_pass_by_reference (cumulative_args_t
, enum machine_mode
,
159 static rtx
visium_function_arg (cumulative_args_t
, enum machine_mode
,
162 static void visium_function_arg_advance (cumulative_args_t
, enum machine_mode
,
165 static bool visium_return_in_memory (const_tree
, const_tree fntype
);
167 static rtx
visium_function_value (const_tree
, const_tree fn_decl_or_type
,
170 static rtx
visium_libcall_value (enum machine_mode
, const_rtx
);
172 static void visium_setup_incoming_varargs (cumulative_args_t
,
176 static void visium_va_start (tree valist
, rtx nextarg
);
178 static tree
visium_gimplify_va_arg (tree
, tree
, gimple_seq
*, gimple_seq
*);
180 static bool visium_function_ok_for_sibcall (tree
, tree
);
182 static bool visium_frame_pointer_required (void);
184 static tree
visium_build_builtin_va_list (void);
186 static rtx_insn
*visium_md_asm_adjust (vec
<rtx
> &, vec
<rtx
> &,
188 vec
<rtx
> &, HARD_REG_SET
&);
190 static bool visium_legitimate_constant_p (enum machine_mode
, rtx
);
192 static bool visium_legitimate_address_p (enum machine_mode
, rtx
, bool);
194 static bool visium_print_operand_punct_valid_p (unsigned char);
195 static void visium_print_operand (FILE *, rtx
, int);
196 static void visium_print_operand_address (FILE *, machine_mode
, rtx
);
198 static void visium_conditional_register_usage (void);
200 static rtx
visium_legitimize_address (rtx
, rtx
, enum machine_mode
);
202 static reg_class_t
visium_secondary_reload (bool, rtx
, reg_class_t
,
204 secondary_reload_info
*);
206 static bool visium_class_likely_spilled_p (reg_class_t
);
208 static void visium_trampoline_init (rtx
, tree
, rtx
);
210 static int visium_issue_rate (void);
212 static int visium_adjust_priority (rtx_insn
*, int);
214 static int visium_adjust_cost (rtx_insn
*, int, rtx_insn
*, int, unsigned int);
216 static int visium_register_move_cost (enum machine_mode
, reg_class_t
,
219 static int visium_memory_move_cost (enum machine_mode
, reg_class_t
, bool);
221 static bool visium_rtx_costs (rtx
, machine_mode
, int, int, int *, bool);
223 static void visium_option_override (void);
225 static void visium_init_libfuncs (void);
227 static unsigned int visium_reorg (void);
229 /* Setup the global target hooks structure. */
231 #undef TARGET_MAX_ANCHOR_OFFSET
232 #define TARGET_MAX_ANCHOR_OFFSET 31
234 #undef TARGET_PASS_BY_REFERENCE
235 #define TARGET_PASS_BY_REFERENCE visium_pass_by_reference
237 #undef TARGET_FUNCTION_ARG
238 #define TARGET_FUNCTION_ARG visium_function_arg
240 #undef TARGET_FUNCTION_ARG_ADVANCE
241 #define TARGET_FUNCTION_ARG_ADVANCE visium_function_arg_advance
243 #undef TARGET_RETURN_IN_MEMORY
244 #define TARGET_RETURN_IN_MEMORY visium_return_in_memory
246 #undef TARGET_FUNCTION_VALUE
247 #define TARGET_FUNCTION_VALUE visium_function_value
249 #undef TARGET_LIBCALL_VALUE
250 #define TARGET_LIBCALL_VALUE visium_libcall_value
252 #undef TARGET_SETUP_INCOMING_VARARGS
253 #define TARGET_SETUP_INCOMING_VARARGS visium_setup_incoming_varargs
255 #undef TARGET_EXPAND_BUILTIN_VA_START
256 #define TARGET_EXPAND_BUILTIN_VA_START visium_va_start
258 #undef TARGET_BUILD_BUILTIN_VA_LIST
259 #define TARGET_BUILD_BUILTIN_VA_LIST visium_build_builtin_va_list
261 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
262 #define TARGET_GIMPLIFY_VA_ARG_EXPR visium_gimplify_va_arg
264 #undef TARGET_LEGITIMATE_CONSTANT_P
265 #define TARGET_LEGITIMATE_CONSTANT_P visium_legitimate_constant_p
267 #undef TARGET_LEGITIMATE_ADDRESS_P
268 #define TARGET_LEGITIMATE_ADDRESS_P visium_legitimate_address_p
270 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
271 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P visium_print_operand_punct_valid_p
272 #undef TARGET_PRINT_OPERAND
273 #define TARGET_PRINT_OPERAND visium_print_operand
274 #undef TARGET_PRINT_OPERAND_ADDRESS
275 #define TARGET_PRINT_OPERAND_ADDRESS visium_print_operand_address
277 #undef TARGET_ATTRIBUTE_TABLE
278 #define TARGET_ATTRIBUTE_TABLE visium_attribute_table
280 #undef TARGET_ADDRESS_COST
281 #define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
283 #undef TARGET_STRICT_ARGUMENT_NAMING
284 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
286 #undef TARGET_SCHED_ISSUE_RATE
287 #define TARGET_SCHED_ISSUE_RATE visium_issue_rate
289 #undef TARGET_SCHED_ADJUST_PRIORITY
290 #define TARGET_SCHED_ADJUST_PRIORITY visium_adjust_priority
292 #undef TARGET_SCHED_ADJUST_COST
293 #define TARGET_SCHED_ADJUST_COST visium_adjust_cost
295 #undef TARGET_MEMORY_MOVE_COST
296 #define TARGET_MEMORY_MOVE_COST visium_memory_move_cost
298 #undef TARGET_REGISTER_MOVE_COST
299 #define TARGET_REGISTER_MOVE_COST visium_register_move_cost
301 #undef TARGET_RTX_COSTS
302 #define TARGET_RTX_COSTS visium_rtx_costs
304 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
305 #define TARGET_FUNCTION_OK_FOR_SIBCALL visium_function_ok_for_sibcall
307 #undef TARGET_FRAME_POINTER_REQUIRED
308 #define TARGET_FRAME_POINTER_REQUIRED visium_frame_pointer_required
310 #undef TARGET_SECONDARY_RELOAD
311 #define TARGET_SECONDARY_RELOAD visium_secondary_reload
313 #undef TARGET_CLASS_LIKELY_SPILLED_P
314 #define TARGET_CLASS_LIKELY_SPILLED_P visium_class_likely_spilled_p
316 #undef TARGET_LEGITIMIZE_ADDRESS
317 #define TARGET_LEGITIMIZE_ADDRESS visium_legitimize_address
319 #undef TARGET_OPTION_OVERRIDE
320 #define TARGET_OPTION_OVERRIDE visium_option_override
322 #undef TARGET_INIT_LIBFUNCS
323 #define TARGET_INIT_LIBFUNCS visium_init_libfuncs
325 #undef TARGET_CONDITIONAL_REGISTER_USAGE
326 #define TARGET_CONDITIONAL_REGISTER_USAGE visium_conditional_register_usage
328 #undef TARGET_TRAMPOLINE_INIT
329 #define TARGET_TRAMPOLINE_INIT visium_trampoline_init
331 #undef TARGET_MD_ASM_ADJUST
332 #define TARGET_MD_ASM_ADJUST visium_md_asm_adjust
334 #undef TARGET_FLAGS_REGNUM
335 #define TARGET_FLAGS_REGNUM FLAGS_REGNUM
337 struct gcc_target targetm
= TARGET_INITIALIZER
;
341 const pass_data pass_data_visium_reorg
=
345 OPTGROUP_NONE
, /* optinfo_flags */
346 TV_MACH_DEP
, /* tv_id */
347 0, /* properties_required */
348 0, /* properties_provided */
349 0, /* properties_destroyed */
350 0, /* todo_flags_start */
351 0, /* todo_flags_finish */
354 class pass_visium_reorg
: public rtl_opt_pass
357 pass_visium_reorg(gcc::context
*ctxt
)
358 : rtl_opt_pass(pass_data_visium_reorg
, ctxt
)
361 /* opt_pass methods: */
362 virtual unsigned int execute (function
*)
364 return visium_reorg ();
367 }; // class pass_work_around_errata
372 make_pass_visium_reorg (gcc::context
*ctxt
)
374 return new pass_visium_reorg (ctxt
);
377 /* Options override for Visium. */
380 visium_option_override (void)
383 warning (OPT_fpic
, "-fpic is not supported");
385 warning (OPT_fPIC
, "-fPIC is not supported");
387 /* MCM is the default in the GR5/GR6 era. */
388 target_flags
|= MASK_MCM
;
390 /* FPU is the default with MCM, but don't override an explicit option. */
391 if ((target_flags_explicit
& MASK_FPU
) == 0)
392 target_flags
|= MASK_FPU
;
394 /* The supervisor mode is the default. */
395 if ((target_flags_explicit
& MASK_SV_MODE
) == 0)
396 target_flags
|= MASK_SV_MODE
;
398 /* The GR6 has the Block Move Instructions and an IEEE-compliant FPU. */
399 if (visium_cpu_and_features
== PROCESSOR_GR6
)
401 target_flags
|= MASK_BMI
;
402 if (target_flags
& MASK_FPU
)
403 target_flags
|= MASK_FPU_IEEE
;
406 /* Set -mtune from -mcpu if not specified. */
407 if (!global_options_set
.x_visium_cpu
)
408 visium_cpu
= visium_cpu_and_features
;
410 /* Align functions on 256-byte (32-quadword) for GR5 and 64-byte (8-quadword)
411 boundaries for GR6 so they start a new burst mode window. */
412 if (align_functions
== 0)
414 if (visium_cpu
== PROCESSOR_GR6
)
415 align_functions
= 64;
417 align_functions
= 256;
419 /* Allow the size of compilation units to double because of inlining.
420 In practice the global size of the object code is hardly affected
421 because the additional instructions will take up the padding. */
422 maybe_set_param_value (PARAM_INLINE_UNIT_GROWTH
, 100,
423 global_options
.x_param_values
,
424 global_options_set
.x_param_values
);
427 /* Likewise for loops. */
428 if (align_loops
== 0)
430 if (visium_cpu
== PROCESSOR_GR6
)
435 /* But not if they are too far away from a 256-byte boundary. */
436 align_loops_max_skip
= 31;
440 /* Align all jumps on quadword boundaries for the burst mode, and even
441 on 8-quadword boundaries for GR6 so they start a new window. */
442 if (align_jumps
== 0)
444 if (visium_cpu
== PROCESSOR_GR6
)
450 /* We register a machine-specific pass. This pass must be scheduled as
451 late as possible so that we have the (essentially) final form of the
452 insn stream to work on. Registering the pass must be done at start up.
453 It's convenient to do it here. */
454 opt_pass
*visium_reorg_pass
= make_pass_visium_reorg (g
);
455 struct register_pass_info insert_pass_visium_reorg
=
457 visium_reorg_pass
, /* pass */
458 "dbr", /* reference_pass_name */
459 1, /* ref_pass_instance_number */
460 PASS_POS_INSERT_AFTER
/* po_op */
462 register_pass (&insert_pass_visium_reorg
);
465 /* Register the Visium-specific libfuncs with the middle-end. */
468 visium_init_libfuncs (void)
471 long_int_memcpy_libfunc
= init_one_libfunc ("__long_int_memcpy");
472 wrd_memcpy_libfunc
= init_one_libfunc ("__wrd_memcpy");
473 byt_memcpy_libfunc
= init_one_libfunc ("__byt_memcpy");
475 long_int_memset_libfunc
= init_one_libfunc ("__long_int_memset");
476 wrd_memset_libfunc
= init_one_libfunc ("__wrd_memset");
477 byt_memset_libfunc
= init_one_libfunc ("__byt_memset");
479 set_trampoline_parity_libfunc
= init_one_libfunc ("__set_trampoline_parity");
482 /* Return the number of instructions that can issue on the same cycle. */
485 visium_issue_rate (void)
500 /* Return the adjusted PRIORITY of INSN. */
503 visium_adjust_priority (rtx_insn
*insn
, int priority
)
505 /* On the GR5, we slightly increase the priority of writes in order to avoid
506 scheduling a read on the next cycle. This is necessary in addition to the
507 associated insn reservation because there are no data dependencies.
508 We also slightly increase the priority of reads from ROM in order to group
509 them as much as possible. These reads are a bit problematic because they
510 conflict with the instruction fetches, i.e. the data and instruction buses
511 tread on each other's toes when they are executed. */
512 if (visium_cpu
== PROCESSOR_GR5
515 && recog_memoized (insn
) >= 0)
517 enum attr_type attr_type
= get_attr_type (insn
);
518 if (attr_type
== TYPE_REG_MEM
519 || (attr_type
== TYPE_MEM_REG
520 && MEM_READONLY_P (SET_SRC (PATTERN (insn
)))))
527 /* Adjust the cost of a scheduling dependency. Return the new cost of
528 a dependency LINK of INSN on DEP_INSN. COST is the current cost. */
531 visium_adjust_cost (rtx_insn
*insn
, int dep_type
, rtx_insn
*dep_insn
, int cost
,
534 enum attr_type attr_type
;
536 /* Don't adjust costs for true dependencies as they are described with
537 bypasses. But we make an exception for the first scheduling pass to
538 help the subsequent postreload compare elimination pass. */
539 if (dep_type
== REG_DEP_TRUE
)
541 if (!reload_completed
542 && recog_memoized (insn
) >= 0
543 && get_attr_type (insn
) == TYPE_CMP
)
545 rtx pat
= PATTERN (insn
);
546 gcc_assert (GET_CODE (pat
) == SET
);
547 rtx src
= SET_SRC (pat
);
549 /* Only the branches can be modified by the postreload compare
550 elimination pass, not the cstores because they accept only
551 unsigned comparison operators and they are eliminated if
552 one of the operands is zero. */
553 if (GET_CODE (src
) == IF_THEN_ELSE
554 && XEXP (XEXP (src
, 0), 1) == const0_rtx
555 && recog_memoized (dep_insn
) >= 0)
557 enum attr_type dep_attr_type
= get_attr_type (dep_insn
);
559 /* The logical instructions use CCmode and thus work with any
560 comparison operator, whereas the arithmetic instructions use
561 CC_NOOVmode and thus work with only a small subset. */
562 if (dep_attr_type
== TYPE_LOGIC
563 || (dep_attr_type
== TYPE_ARITH
564 && visium_noov_operator (XEXP (src
, 0),
565 GET_MODE (XEXP (src
, 0)))))
573 if (recog_memoized (insn
) < 0)
576 attr_type
= get_attr_type (insn
);
578 /* Anti dependency: DEP_INSN reads a register that INSN writes some
580 if (dep_type
== REG_DEP_ANTI
)
582 /* On the GR5, the latency of FP instructions needs to be taken into
583 account for every dependency involving a write. */
584 if (attr_type
== TYPE_REG_FP
&& visium_cpu
== PROCESSOR_GR5
)
587 rtx pat
= PATTERN (insn
);
588 rtx dep_pat
= PATTERN (dep_insn
);
590 if (GET_CODE (pat
) != SET
|| GET_CODE (dep_pat
) != SET
)
591 /* If this happens, we have to extend this to schedule
592 optimally. Return 0 for now. */
595 if (reg_mentioned_p (SET_DEST (pat
), SET_SRC (dep_pat
)))
597 if (recog_memoized (dep_insn
) < 0)
600 switch (get_attr_type (dep_insn
))
608 /* A fload can't be issued until a preceding arithmetic
609 operation has finished if the target of the fload is
610 any of the sources (or destination) of the arithmetic
611 operation. Note that the latency may be (much)
612 greater than this if the preceding instruction
613 concerned is in a queue. */
614 return insn_default_latency (dep_insn
);
622 /* On the GR6, we try to make sure that the link register is restored
623 sufficiently ahead of the return as to yield a correct prediction
624 from the branch predictor. By default there is no true dependency
625 but an anti dependency between them, so we simply reuse it. */
626 else if (attr_type
== TYPE_RET
&& visium_cpu
== PROCESSOR_GR6
)
628 rtx dep_pat
= PATTERN (dep_insn
);
629 if (GET_CODE (dep_pat
) == SET
630 && REG_P (SET_DEST (dep_pat
))
631 && REGNO (SET_DEST (dep_pat
)) == LINK_REGNUM
)
635 /* For other anti dependencies, the cost is 0. */
639 /* Output dependency: DEP_INSN writes a register that INSN writes some
641 else if (dep_type
== REG_DEP_OUTPUT
)
643 /* On the GR5, the latency of FP instructions needs to be taken into
644 account for every dependency involving a write. */
645 if (attr_type
== TYPE_REG_FP
&& visium_cpu
== PROCESSOR_GR5
)
648 rtx pat
= PATTERN (insn
);
649 rtx dep_pat
= PATTERN (dep_insn
);
651 if (GET_CODE (pat
) != SET
|| GET_CODE (dep_pat
) != SET
)
652 /* If this happens, we have to extend this to schedule
653 optimally. Return 0 for now. */
656 if (reg_mentioned_p (SET_DEST (pat
), SET_DEST (dep_pat
)))
658 if (recog_memoized (dep_insn
) < 0)
661 switch (get_attr_type (dep_insn
))
669 /* A fload can't be issued until a preceding arithmetic
670 operation has finished if the target of the fload is
671 the destination of the arithmetic operation. Note that
672 the latency may be (much) greater than this if the
673 preceding instruction concerned is in a queue. */
674 return insn_default_latency (dep_insn
);
682 /* For other output dependencies, the cost is 0. */
689 /* Handle an "interrupt_handler" attribute; arguments as in
690 struct attribute_spec.handler. */
693 visium_handle_interrupt_attr (tree
*node
, tree name
,
694 tree args ATTRIBUTE_UNUSED
,
695 int flags ATTRIBUTE_UNUSED
,
698 if (TREE_CODE (*node
) != FUNCTION_DECL
)
700 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
702 *no_add_attrs
= true;
704 else if (!TARGET_SV_MODE
)
706 error ("an interrupt handler cannot be compiled with -muser-mode");
707 *no_add_attrs
= true;
713 /* Return non-zero if the current function is an interrupt function. */
716 visium_interrupt_function_p (void)
719 lookup_attribute ("interrupt",
720 DECL_ATTRIBUTES (current_function_decl
)) != NULL_TREE
;
723 /* Conditionally modify the settings of the register file. */
726 visium_conditional_register_usage (void)
728 /* If the supervisor mode is disabled, mask some general registers. */
731 if (visium_cpu_and_features
== PROCESSOR_GR5
)
733 fixed_regs
[24] = call_used_regs
[24] = 1;
734 fixed_regs
[25] = call_used_regs
[25] = 1;
735 fixed_regs
[26] = call_used_regs
[26] = 1;
736 fixed_regs
[27] = call_used_regs
[27] = 1;
737 fixed_regs
[28] = call_used_regs
[28] = 1;
738 call_really_used_regs
[24] = 0;
739 call_really_used_regs
[25] = 0;
740 call_really_used_regs
[26] = 0;
741 call_really_used_regs
[27] = 0;
742 call_really_used_regs
[28] = 0;
745 fixed_regs
[31] = call_used_regs
[31] = 1;
746 call_really_used_regs
[31] = 0;
748 /* We also need to change the long-branch register. */
749 if (visium_cpu_and_features
== PROCESSOR_GR5
)
750 long_branch_regnum
= 20;
752 long_branch_regnum
= 28;
755 /* If the FPU is disabled, mask the FP registers. */
758 for (int i
= FP_FIRST_REGNUM
; i
<= FP_LAST_REGNUM
; i
++)
760 fixed_regs
[i
] = call_used_regs
[i
] = 1;
761 call_really_used_regs
[i
] = 0;
766 /* Prepend to CLOBBERS hard registers that are automatically clobbered for
767 an asm We do this for the FLAGS to maintain source compatibility with
768 the original cc0-based compiler. */
771 visium_md_asm_adjust (vec
<rtx
> &/*outputs*/, vec
<rtx
> &/*inputs*/,
772 vec
<const char *> &/*constraints*/,
773 vec
<rtx
> &clobbers
, HARD_REG_SET
&clobbered_regs
)
775 clobbers
.safe_push (gen_rtx_REG (CCmode
, FLAGS_REGNUM
));
776 SET_HARD_REG_BIT (clobbered_regs
, FLAGS_REGNUM
);
780 /* Return true if X is a legitimate constant for a MODE immediate operand.
781 X is guaranteed to satisfy the CONSTANT_P predicate. */
784 visium_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED
,
785 rtx x ATTRIBUTE_UNUSED
)
790 /* Compute the alignment for a variable. The alignment of an aggregate is
791 set to be at least that of a scalar less than or equal to it in size. */
794 visium_data_alignment (tree type
, unsigned int align
)
796 if (AGGREGATE_TYPE_P (type
)
798 && TREE_CODE (TYPE_SIZE (type
)) == INTEGER_CST
&& align
< 32)
800 if (TREE_INT_CST_LOW (TYPE_SIZE (type
)) >= 32)
803 if (TREE_INT_CST_LOW (TYPE_SIZE (type
)) >= 16 && align
< 16)
810 /* Helper function for HARD_REGNO_RENAME_OK (FROM, TO). Return non-zero if
811 it is OK to rename a hard register FROM to another hard register TO. */
814 visium_hard_regno_rename_ok (unsigned int from ATTRIBUTE_UNUSED
,
817 /* If the function doesn't save LR, then the long-branch register will be
818 used for long branches so we need to know whether it is live before the
819 frame layout is computed. */
820 if (!current_function_saves_lr () && to
== long_branch_regnum
)
823 /* Interrupt functions can only use registers that have already been
824 saved by the prologue, even if they would normally be call-clobbered. */
826 && !df_regs_ever_live_p (to
)
827 && visium_interrupt_function_p ())
833 /* Return true if it is ok to do sibling call optimization for the specified
834 call expression EXP. DECL will be the called function, or NULL if this
835 is an indirect call. */
838 visium_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED
,
839 tree exp ATTRIBUTE_UNUSED
)
841 return !visium_interrupt_function_p ();
844 /* Prepare operands for a move define_expand in MODE. */
847 prepare_move_operands (rtx
*operands
, enum machine_mode mode
)
849 /* If the output is not a register, the input must be. */
850 if (GET_CODE (operands
[0]) == MEM
&& !reg_or_0_operand (operands
[1], mode
))
851 operands
[1] = force_reg (mode
, operands
[1]);
854 /* Return true if the operands are valid for a simple move insn. */
857 ok_for_simple_move_operands (rtx
*operands
, enum machine_mode mode
)
859 /* One of the operands must be a register. */
860 if (!register_operand (operands
[0], mode
)
861 && !reg_or_0_operand (operands
[1], mode
))
864 /* Once the flags are exposed, no simple moves between integer registers. */
865 if (visium_flags_exposed
866 && gpc_reg_operand (operands
[0], mode
)
867 && gpc_reg_operand (operands
[1], mode
))
873 /* Return true if the operands are valid for a simple move strict insn. */
876 ok_for_simple_move_strict_operands (rtx
*operands
, enum machine_mode mode
)
878 /* Once the flags are exposed, no simple moves between integer registers.
879 Note that, in QImode only, a zero source counts as an integer register
880 since it will be emitted as r0. */
881 if (visium_flags_exposed
882 && gpc_reg_operand (operands
[0], mode
)
883 && (gpc_reg_operand (operands
[1], mode
)
884 || (mode
== QImode
&& operands
[1] == const0_rtx
)))
890 /* Return true if the operands are valid for a simple arithmetic or logical
894 ok_for_simple_arith_logic_operands (rtx
*, enum machine_mode
)
896 /* Once the flags are exposed, no simple arithmetic or logical operations
897 between integer registers. */
898 return !visium_flags_exposed
;
901 /* Return non-zero if a branch or call instruction will be emitting a nop
902 into its delay slot. */
905 empty_delay_slot (rtx_insn
*insn
)
909 /* If no previous instruction (should not happen), return true. */
910 if (PREV_INSN (insn
) == NULL
)
913 seq
= NEXT_INSN (PREV_INSN (insn
));
914 if (GET_CODE (PATTERN (seq
)) == SEQUENCE
)
920 /* Wrapper around single_set which returns the first SET of a pair if the
921 second SET is to the flags register. */
924 single_set_and_flags (rtx_insn
*insn
)
926 if (multiple_sets (insn
))
928 rtx pat
= PATTERN (insn
);
929 if (XVECLEN (pat
, 0) == 2
930 && GET_CODE (XVECEXP (pat
, 0, 1)) == SET
931 && REG_P (SET_DEST (XVECEXP (pat
, 0, 1)))
932 && REGNO (SET_DEST (XVECEXP (pat
, 0, 1))) == FLAGS_REGNUM
)
933 return XVECEXP (pat
, 0, 0);
936 return single_set (insn
);
939 /* This is called with OUT_INSN an instruction setting a (base) register
940 and IN_INSN a read or a write. Return 1 if these instructions together
941 constitute a pipeline hazard.
943 On the original architecture, a pipeline data hazard occurs when the Dest
944 of one instruction becomes the SrcA for an immediately following READ or
945 WRITE instruction with a non-zero index (indexing occurs at the decode
946 stage and so a NOP must be inserted in-between for this to work).
953 On the MCM, the non-zero index condition is lifted but the hazard is
954 patched up by the hardware through the injection of wait states:
959 We nevertheless try to schedule instructions around this. */
962 gr5_hazard_bypass_p (rtx_insn
*out_insn
, rtx_insn
*in_insn
)
964 rtx out_set
, in_set
, dest
, memexpr
;
965 unsigned int out_reg
, in_reg
;
967 /* A CALL is storage register class, but the link register is of no
969 if (GET_CODE (out_insn
) == CALL_INSN
)
972 out_set
= single_set_and_flags (out_insn
);
973 dest
= SET_DEST (out_set
);
975 /* Should be no stall/hazard if OUT_INSN is MEM := ???. This only
976 occurs prior to reload. */
977 if (GET_CODE (dest
) == MEM
)
980 if (GET_CODE (dest
) == STRICT_LOW_PART
)
981 dest
= XEXP (dest
, 0);
982 if (GET_CODE (dest
) == SUBREG
)
983 dest
= SUBREG_REG (dest
);
984 out_reg
= REGNO (dest
);
986 in_set
= single_set_and_flags (in_insn
);
988 /* If IN_INSN is MEM := MEM, it's the source that counts. */
989 if (GET_CODE (SET_SRC (in_set
)) == MEM
)
990 memexpr
= XEXP (SET_SRC (in_set
), 0);
992 memexpr
= XEXP (SET_DEST (in_set
), 0);
994 if (GET_CODE (memexpr
) == PLUS
)
996 memexpr
= XEXP (memexpr
, 0);
997 if (GET_CODE (memexpr
) == SUBREG
)
998 in_reg
= REGNO (SUBREG_REG (memexpr
));
1000 in_reg
= REGNO (memexpr
);
1002 if (in_reg
== out_reg
)
1005 else if (TARGET_MCM
)
1007 if (GET_CODE (memexpr
) == STRICT_LOW_PART
)
1008 memexpr
= XEXP (memexpr
, 0);
1009 if (GET_CODE (memexpr
) == SUBREG
)
1010 memexpr
= SUBREG_REG (memexpr
);
1011 in_reg
= REGNO (memexpr
);
1013 if (in_reg
== out_reg
)
1020 /* Return true if INSN is an empty asm instruction. */
1023 empty_asm_p (rtx insn
)
1025 rtx body
= PATTERN (insn
);
1028 if (GET_CODE (body
) == ASM_INPUT
)
1029 templ
= XSTR (body
, 0);
1030 else if (asm_noperands (body
) >= 0)
1031 templ
= decode_asm_operands (body
, NULL
, NULL
, NULL
, NULL
, NULL
);
1035 return (templ
&& templ
[0] == '\0');
1038 /* Insert a NOP immediately before INSN wherever there is a pipeline hazard.
1039 LAST_REG records the register set in the last insn and LAST_INSN_CALL
1040 records whether the last insn was a call insn. */
1043 gr5_avoid_hazard (rtx_insn
*insn
, unsigned int *last_reg
, bool *last_insn_call
)
1045 unsigned int dest_reg
= 0;
1048 switch (GET_CODE (insn
))
1052 *last_insn_call
= true;
1056 /* If this is an empty asm, just skip it. */
1057 if (!empty_asm_p (insn
))
1060 *last_insn_call
= false;
1065 /* If this is an empty asm, just skip it. */
1066 if (empty_asm_p (insn
))
1074 set
= single_set_and_flags (insn
);
1075 if (set
!= NULL_RTX
)
1077 rtx dest
= SET_DEST (set
);
1078 const bool double_p
= GET_MODE_SIZE (GET_MODE (dest
)) > UNITS_PER_WORD
;
1081 if (GET_CODE (SET_SRC (set
)) == MEM
)
1083 memrtx
= XEXP (SET_SRC (set
), 0);
1084 if (GET_CODE (dest
) == STRICT_LOW_PART
)
1085 dest
= XEXP (dest
, 0);
1087 dest_reg
= REGNO (dest
);
1089 /* If this is a DI or DF mode memory to register
1090 copy, then if rd = rs we get
1095 otherwise the order is
1102 unsigned int base_reg
;
1104 if (GET_CODE (memrtx
) == PLUS
)
1105 base_reg
= REGNO (XEXP (memrtx
, 0));
1107 base_reg
= REGNO (memrtx
);
1109 if (dest_reg
!= base_reg
)
1114 else if (GET_CODE (dest
) == MEM
)
1115 memrtx
= XEXP (dest
, 0);
1117 else if (GET_MODE_CLASS (GET_MODE (dest
)) != MODE_CC
)
1119 if (GET_CODE (dest
) == STRICT_LOW_PART
1120 ||GET_CODE (dest
) == ZERO_EXTRACT
)
1121 dest
= XEXP (dest
, 0);
1122 dest_reg
= REGNO (dest
);
1124 if (GET_CODE (SET_SRC (set
)) == REG
)
1126 unsigned int srcreg
= REGNO (SET_SRC (set
));
1128 /* Check for rs := rs, which will be deleted. */
1129 if (srcreg
== dest_reg
)
1132 /* In the case of a DI or DF mode move from register to
1133 register there is overlap if rd = rs + 1 in which case
1134 the order of the copies is reversed :
1139 if (double_p
&& dest_reg
!= srcreg
+ 1)
1144 /* If this is the delay slot of a call insn, any register it sets
1146 if (*last_insn_call
)
1149 /* If the previous insn sets the value of a register, and this insn
1150 uses a base register, check for the pipeline hazard where it is
1151 the same register in each case. */
1152 if (*last_reg
!= 0 && memrtx
!= NULL_RTX
)
1154 unsigned int reg
= 0;
1156 /* Check for an index (original architecture). */
1157 if (GET_CODE (memrtx
) == PLUS
)
1158 reg
= REGNO (XEXP (memrtx
, 0));
1160 /* Check for an MCM target or rs := [rs], in DI or DF mode. */
1161 else if (TARGET_MCM
|| (double_p
&& REGNO (memrtx
) == dest_reg
))
1162 reg
= REGNO (memrtx
);
1164 /* Remove any pipeline hazard by inserting a NOP. */
1165 if (reg
== *last_reg
)
1169 "inserting nop before insn %d\n", INSN_UID (insn
));
1170 emit_insn_after (gen_hazard_nop (), prev_active_insn (insn
));
1171 emit_insn_after (gen_blockage (), insn
);
1175 *last_reg
= dest_reg
;
1178 *last_insn_call
= false;
1181 /* Go through the instruction stream and insert nops where necessary to avoid
1182 pipeline hazards. There are two cases:
1184 1. On the original architecture, it is invalid to set the value of a
1185 (base) register and then use it in an address with a non-zero index
1186 in the next instruction.
1188 2. On the MCM, setting the value of a (base) register and then using
1189 it in address (including with zero index) in the next instruction
1190 will result in a pipeline stall of 3 cycles. */
1193 gr5_hazard_avoidance (void)
1195 unsigned int last_reg
= 0;
1196 bool last_insn_call
= false;
1199 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
1202 rtx pat
= PATTERN (insn
);
1204 if (GET_CODE (pat
) == SEQUENCE
)
1206 for (int i
= 0; i
< XVECLEN (pat
, 0); i
++)
1207 gr5_avoid_hazard (as_a
<rtx_insn
*> (XVECEXP (pat
, 0, i
)),
1208 &last_reg
, &last_insn_call
);
1211 else if (GET_CODE (insn
) == CALL_INSN
)
1213 /* This call is going to get a nop in its delay slot. */
1215 last_insn_call
= false;
1219 gr5_avoid_hazard (insn
, &last_reg
, &last_insn_call
);
1222 else if (GET_CODE (insn
) == BARRIER
)
1226 /* Perform a target-specific pass over the instruction stream. The compiler
1227 will run it at all optimization levels, just after the point at which it
1228 normally does delayed-branch scheduling. */
1233 if (visium_cpu
== PROCESSOR_GR5
)
1234 gr5_hazard_avoidance ();
1238 /* Return true if an argument must be passed by indirect reference. */
1241 visium_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED
,
1242 enum machine_mode mode ATTRIBUTE_UNUSED
,
1244 bool named ATTRIBUTE_UNUSED
)
1246 return type
&& (AGGREGATE_TYPE_P (type
) || TREE_CODE (type
) == VECTOR_TYPE
);
1249 /* Define how arguments are passed.
1251 A range of general registers and floating registers is available
1252 for passing arguments. When the class of registers which an
1253 argument would normally use is exhausted, that argument, is passed
1254 in the overflow region of the stack. No argument is split between
1255 registers and stack.
1257 Arguments of type float or _Complex float go in FP registers if FP
1258 hardware is available. If there is no FP hardware, arguments of
1259 type float go in general registers. All other arguments are passed
1260 in general registers. */
1263 visium_function_arg (cumulative_args_t pcum_v
, enum machine_mode mode
,
1264 const_tree type ATTRIBUTE_UNUSED
,
1265 bool named ATTRIBUTE_UNUSED
)
1268 CUMULATIVE_ARGS
*ca
= get_cumulative_args (pcum_v
);
1270 size
= (GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
1271 if (mode
== VOIDmode
)
1274 /* Scalar or complex single precision floating point arguments are returned
1275 in floating registers. */
1277 && ((GET_MODE_CLASS (mode
) == MODE_FLOAT
1278 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
)
1279 || (GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
1280 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
* 2)))
1282 if (ca
->frcount
+ size
<= MAX_ARGS_IN_FP_REGISTERS
)
1283 return gen_rtx_REG (mode
, FP_ARG_FIRST
+ ca
->frcount
);
1288 if (ca
->grcount
+ size
<= MAX_ARGS_IN_GP_REGISTERS
)
1289 return gen_rtx_REG (mode
, ca
->grcount
+ GP_ARG_FIRST
);
1294 /* Update the summarizer variable pointed to by PCUM_V to advance past an
1295 argument in the argument list. The values MODE, TYPE and NAMED describe
1296 that argument. Once this is done, the variable CUM is suitable for
1297 analyzing the _following_ argument with visium_function_arg. */
1300 visium_function_arg_advance (cumulative_args_t pcum_v
,
1301 enum machine_mode mode
,
1302 const_tree type ATTRIBUTE_UNUSED
,
1305 int size
= (GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
1307 CUMULATIVE_ARGS
*ca
= get_cumulative_args (pcum_v
);
1309 /* Scalar or complex single precision floating point arguments are returned
1310 in floating registers. */
1312 && ((GET_MODE_CLASS (mode
) == MODE_FLOAT
1313 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
)
1314 || (GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
1315 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
* 2)))
1317 if (ca
->frcount
+ size
<= MAX_ARGS_IN_FP_REGISTERS
)
1318 ca
->frcount
+= size
;
1322 ca
->frcount
= MAX_ARGS_IN_FP_REGISTERS
;
1327 /* Everything else goes in a general register, if enough are
1329 if (ca
->grcount
+ size
<= MAX_ARGS_IN_GP_REGISTERS
)
1330 ca
->grcount
+= size
;
1334 ca
->grcount
= MAX_ARGS_IN_GP_REGISTERS
;
1339 ca
->stack_words
+= stack_size
;
1342 /* Specify whether to return the return value in memory. */
1345 visium_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
1347 return (AGGREGATE_TYPE_P (type
) || TREE_CODE (type
) == VECTOR_TYPE
);
1350 /* Define how scalar values are returned. */
1353 visium_function_value_1 (enum machine_mode mode
)
1355 /* Scalar or complex single precision floating point values
1356 are returned in floating register f1. */
1358 && ((GET_MODE_CLASS (mode
) == MODE_FLOAT
1359 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
)
1360 || (GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
1361 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
* 2)))
1362 return gen_rtx_REG (mode
, FP_RETURN_REGNUM
);
1364 /* All others are returned in r1. */
1365 return gen_rtx_REG (mode
, RETURN_REGNUM
);
1368 /* Return an RTX representing the place where a function returns or receives
1369 a value of data type RET_TYPE. */
1372 visium_function_value (const_tree ret_type
,
1373 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1374 bool outgoing ATTRIBUTE_UNUSED
)
1376 return visium_function_value_1 (TYPE_MODE (ret_type
));
1379 /* Return an RTX representing the place where the library function result will
1383 visium_libcall_value (enum machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
1385 return visium_function_value_1 (mode
);
1388 /* Store the anonymous register arguments into the stack so that all the
1389 arguments appear to have been passed consecutively on the stack. */
1392 visium_setup_incoming_varargs (cumulative_args_t pcum_v
,
1393 enum machine_mode mode
,
1395 int *pretend_size ATTRIBUTE_UNUSED
,
1398 cumulative_args_t local_args_so_far
;
1399 CUMULATIVE_ARGS local_copy
;
1400 CUMULATIVE_ARGS
*locargs
;
1401 int gp_saved
, fp_saved
, size
;
1403 /* Create an internal cumulative_args_t pointer to internally define
1404 storage to ensure calling TARGET_FUNCTION_ARG_ADVANCE does not
1405 make global changes. */
1406 local_args_so_far
.p
= &local_copy
;
1407 locargs
= get_cumulative_args (pcum_v
);
1410 local_args_so_far
.magic
= CUMULATIVE_ARGS_MAGIC
;
1413 local_copy
.grcount
= locargs
->grcount
;
1414 local_copy
.frcount
= locargs
->frcount
;
1415 local_copy
.stack_words
= locargs
->stack_words
;
1417 /* The caller has advanced ARGS_SO_FAR up to, but not beyond, the last named
1418 argument. Advance a local copy of ARGS_SO_FAR past the last "real" named
1419 argument, to find out how many registers are left over. */
1420 TARGET_FUNCTION_ARG_ADVANCE (local_args_so_far
, mode
, type
, 1);
1422 /* Find how many registers we need to save. */
1423 locargs
= get_cumulative_args (local_args_so_far
);
1424 gp_saved
= MAX_ARGS_IN_GP_REGISTERS
- locargs
->grcount
;
1425 fp_saved
= (TARGET_FPU
? MAX_ARGS_IN_FP_REGISTERS
- locargs
->frcount
: 0);
1426 size
= (gp_saved
* UNITS_PER_WORD
) + (fp_saved
* UNITS_PER_HWFPVALUE
);
1428 if (!no_rtl
&& size
> 0)
1430 /* To avoid negative offsets, which are not valid addressing modes on
1431 the Visium, we create a base register for the pretend args. */
1434 plus_constant (Pmode
, virtual_incoming_args_rtx
, -size
));
1439 = gen_rtx_MEM (BLKmode
,
1440 plus_constant (Pmode
,
1442 fp_saved
* UNITS_PER_HWFPVALUE
));
1443 MEM_NOTRAP_P (mem
) = 1;
1444 set_mem_alias_set (mem
, get_varargs_alias_set ());
1445 move_block_from_reg (locargs
->grcount
+ GP_ARG_FIRST
, mem
, gp_saved
);
1450 rtx mem
= gen_rtx_MEM (BLKmode
, ptr
);
1451 MEM_NOTRAP_P (mem
) = 1;
1452 set_mem_alias_set (mem
, get_varargs_alias_set ());
1453 gcc_assert (UNITS_PER_WORD
== UNITS_PER_HWFPVALUE
);
1454 move_block_from_reg (locargs
->frcount
+ FP_ARG_FIRST
, mem
, fp_saved
);
1458 visium_reg_parm_save_area_size
= size
;
1461 /* Define the `__builtin_va_list' type for the ABI. */
1464 visium_build_builtin_va_list (void)
1466 tree f_ovfl
, f_gbase
, f_fbase
, f_gbytes
, f_fbytes
, record
;
1468 record
= (*lang_hooks
.types
.make_type
) (RECORD_TYPE
);
1469 f_ovfl
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1470 get_identifier ("__overflow_argptr"), ptr_type_node
);
1471 f_gbase
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1472 get_identifier ("__gpr_base"), ptr_type_node
);
1473 f_fbase
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1474 get_identifier ("__fpr_base"), ptr_type_node
);
1475 f_gbytes
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1476 get_identifier ("__gpr_bytes"),
1477 short_unsigned_type_node
);
1478 f_fbytes
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1479 get_identifier ("__fpr_bytes"),
1480 short_unsigned_type_node
);
1482 DECL_FIELD_CONTEXT (f_ovfl
) = record
;
1483 DECL_FIELD_CONTEXT (f_gbase
) = record
;
1484 DECL_FIELD_CONTEXT (f_fbase
) = record
;
1485 DECL_FIELD_CONTEXT (f_gbytes
) = record
;
1486 DECL_FIELD_CONTEXT (f_fbytes
) = record
;
1487 TYPE_FIELDS (record
) = f_ovfl
;
1488 TREE_CHAIN (f_ovfl
) = f_gbase
;
1489 TREE_CHAIN (f_gbase
) = f_fbase
;
1490 TREE_CHAIN (f_fbase
) = f_gbytes
;
1491 TREE_CHAIN (f_gbytes
) = f_fbytes
;
1492 layout_type (record
);
1497 /* Implement `va_start' for varargs and stdarg. */
1500 visium_va_start (tree valist
, rtx nextarg ATTRIBUTE_UNUSED
)
1502 const CUMULATIVE_ARGS
*ca
= &crtl
->args
.info
;
1503 int gp_saved
= MAX_ARGS_IN_GP_REGISTERS
- ca
->grcount
;
1504 int fp_saved
= (TARGET_FPU
? MAX_ARGS_IN_FP_REGISTERS
- ca
->frcount
: 0);
1505 int named_stack_size
= ca
->stack_words
* UNITS_PER_WORD
, offset
;
1506 tree f_ovfl
, f_gbase
, f_fbase
, f_gbytes
, f_fbytes
;
1507 tree ovfl
, gbase
, gbytes
, fbase
, fbytes
, t
;
1509 f_ovfl
= TYPE_FIELDS (va_list_type_node
);
1510 f_gbase
= TREE_CHAIN (f_ovfl
);
1511 f_fbase
= TREE_CHAIN (f_gbase
);
1512 f_gbytes
= TREE_CHAIN (f_fbase
);
1513 f_fbytes
= TREE_CHAIN (f_gbytes
);
1514 ovfl
= build3 (COMPONENT_REF
, TREE_TYPE (f_ovfl
), valist
, f_ovfl
, NULL_TREE
);
1515 gbase
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbase
), valist
, f_gbase
,
1517 fbase
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbase
), valist
, f_fbase
,
1519 gbytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbytes
), valist
, f_gbytes
,
1521 fbytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbytes
), valist
, f_fbytes
,
1524 /* Store the stacked vararg pointer in the OVFL member. */
1525 t
= make_tree (TREE_TYPE (ovfl
), virtual_incoming_args_rtx
);
1526 t
= fold_build_pointer_plus_hwi (t
, named_stack_size
);
1527 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ovfl
), ovfl
, t
);
1528 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1530 /* Store the base address of the GPR save area into GBASE. */
1531 t
= make_tree (TREE_TYPE (gbase
), virtual_incoming_args_rtx
);
1532 offset
= MAX_ARGS_IN_GP_REGISTERS
* UNITS_PER_WORD
;
1533 t
= fold_build_pointer_plus_hwi (t
, -offset
);
1534 t
= build2 (MODIFY_EXPR
, TREE_TYPE (gbase
), gbase
, t
);
1535 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1537 /* Store the base address of the FPR save area into FBASE. */
1540 t
= make_tree (TREE_TYPE (fbase
), virtual_incoming_args_rtx
);
1541 offset
= gp_saved
* UNITS_PER_WORD
1542 + MAX_ARGS_IN_FP_REGISTERS
* UNITS_PER_HWFPVALUE
;
1543 t
= fold_build_pointer_plus_hwi (t
, -offset
);
1544 t
= build2 (MODIFY_EXPR
, TREE_TYPE (fbase
), fbase
, t
);
1545 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1548 /* Fill in the GBYTES member. */
1549 t
= build2 (MODIFY_EXPR
, TREE_TYPE (gbytes
), gbytes
,
1550 size_int (gp_saved
* UNITS_PER_WORD
));
1551 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1553 /* Fill in the FBYTES member. */
1554 t
= build2 (MODIFY_EXPR
, TREE_TYPE (fbytes
),
1555 fbytes
, size_int (fp_saved
* UNITS_PER_HWFPVALUE
));
1556 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1559 /* Implement `va_arg'. */
1562 visium_gimplify_va_arg (tree valist
, tree type
, gimple_seq
*pre_p
,
1565 tree f_ovfl
, f_gbase
, f_fbase
, f_gbytes
, f_fbytes
;
1566 tree ovfl
, base
, bytes
;
1567 HOST_WIDE_INT size
, rsize
;
1568 const bool by_reference_p
1569 = pass_by_reference (NULL
, TYPE_MODE (type
), type
, false);
1570 const bool float_reg_arg_p
1571 = (TARGET_FPU
&& !by_reference_p
1572 && ((GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
1573 && GET_MODE_SIZE (TYPE_MODE (type
)) <= UNITS_PER_HWFPVALUE
)
1574 || (GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_COMPLEX_FLOAT
1575 && (GET_MODE_SIZE (TYPE_MODE (type
))
1576 <= UNITS_PER_HWFPVALUE
* 2))));
1577 const int max_save_area_size
1578 = (float_reg_arg_p
? MAX_ARGS_IN_FP_REGISTERS
* UNITS_PER_HWFPVALUE
1579 : MAX_ARGS_IN_GP_REGISTERS
* UNITS_PER_WORD
);
1581 tree lab_false
, lab_over
, addr
;
1582 tree ptrtype
= build_pointer_type (type
);
1586 t
= visium_gimplify_va_arg (valist
, ptrtype
, pre_p
, post_p
);
1587 return build_va_arg_indirect_ref (t
);
1590 size
= int_size_in_bytes (type
);
1591 rsize
= (size
+ UNITS_PER_WORD
- 1) & -UNITS_PER_WORD
;
1592 f_ovfl
= TYPE_FIELDS (va_list_type_node
);
1593 f_gbase
= TREE_CHAIN (f_ovfl
);
1594 f_fbase
= TREE_CHAIN (f_gbase
);
1595 f_gbytes
= TREE_CHAIN (f_fbase
);
1596 f_fbytes
= TREE_CHAIN (f_gbytes
);
1598 /* We maintain separate pointers and offsets for floating-point and
1599 general registers, but we need similar code in both cases.
1603 BYTES be the number of unused bytes in the register save area.
1604 BASE be the base address of the register save area.
1605 OFFS be the current offset into the register save area. Either
1606 MAX_ARGS_IN_GP_REGISTERS * UNITS_PER_WORD - bytes or
1607 MAX_ARGS_IN_FP_REGISTERS * UNITS_PER_HWFPVALUE - bytes
1608 depending upon whether the argument is in general or floating
1610 ADDR_RTX be the address of the argument.
1611 RSIZE be the size in bytes of the argument.
1612 OVFL be the pointer to the stack overflow area.
1614 The code we want is:
1616 1: if (bytes >= rsize)
1618 3: addr_rtx = base + offs;
1630 addr
= create_tmp_var (ptr_type_node
, "addr");
1631 lab_false
= create_artificial_label (UNKNOWN_LOCATION
);
1632 lab_over
= create_artificial_label (UNKNOWN_LOCATION
);
1633 if (float_reg_arg_p
)
1634 bytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbytes
), unshare_expr (valist
),
1635 f_fbytes
, NULL_TREE
);
1637 bytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbytes
), unshare_expr (valist
),
1638 f_gbytes
, NULL_TREE
);
1640 /* [1] Emit code to branch if bytes < rsize. */
1641 t
= fold_convert (TREE_TYPE (bytes
), size_int (rsize
));
1642 t
= build2 (LT_EXPR
, boolean_type_node
, bytes
, t
);
1643 u
= build1 (GOTO_EXPR
, void_type_node
, lab_false
);
1644 t
= build3 (COND_EXPR
, void_type_node
, t
, u
, NULL_TREE
);
1645 gimplify_and_add (t
, pre_p
);
1647 /* [3] Emit code for: addr_rtx = base + offs, where
1648 offs = max_save_area_size - bytes. */
1649 t
= fold_convert (sizetype
, bytes
);
1650 offs
= build2 (MINUS_EXPR
, sizetype
, size_int (max_save_area_size
), t
);
1651 if (float_reg_arg_p
)
1652 base
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbase
), valist
, f_fbase
,
1655 base
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbase
), valist
, f_gbase
,
1658 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (base
), base
, offs
);
1659 t
= build2 (MODIFY_EXPR
, void_type_node
, addr
, t
);
1660 gimplify_and_add (t
, pre_p
);
1662 /* [4] Emit code for: bytes -= rsize. */
1663 t
= fold_convert (TREE_TYPE (bytes
), size_int (rsize
));
1664 t
= build2 (MINUS_EXPR
, TREE_TYPE (bytes
), bytes
, t
);
1665 t
= build2 (MODIFY_EXPR
, TREE_TYPE (bytes
), bytes
, t
);
1666 gimplify_and_add (t
, pre_p
);
1668 /* [6] Emit code to branch over the else clause, then the label. */
1669 t
= build1 (GOTO_EXPR
, void_type_node
, lab_over
);
1670 gimplify_and_add (t
, pre_p
);
1671 t
= build1 (LABEL_EXPR
, void_type_node
, lab_false
);
1672 gimplify_and_add (t
, pre_p
);
1674 /* [8] Emit code for: bytes = 0. */
1675 t
= fold_convert (TREE_TYPE (bytes
), size_int (0));
1676 t
= build2 (MODIFY_EXPR
, TREE_TYPE (bytes
), unshare_expr (bytes
), t
);
1677 gimplify_and_add (t
, pre_p
);
1679 /* [9] Emit code for: addr_rtx = ovfl. */
1680 ovfl
= build3 (COMPONENT_REF
, TREE_TYPE (f_ovfl
), valist
, f_ovfl
, NULL_TREE
);
1681 t
= build2 (MODIFY_EXPR
, void_type_node
, addr
, ovfl
);
1682 gimplify_and_add (t
, pre_p
);
1684 /* [10] Emit code for: ovfl += rsize. */
1685 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (ovfl
), ovfl
, size_int (rsize
));
1686 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ovfl
), unshare_expr (ovfl
), t
);
1687 gimplify_and_add (t
, pre_p
);
1688 t
= build1 (LABEL_EXPR
, void_type_node
, lab_over
);
1689 gimplify_and_add (t
, pre_p
);
1690 addr
= fold_convert (ptrtype
, addr
);
1692 return build_va_arg_indirect_ref (addr
);
1695 /* Return true if OP is an offset suitable for use as a displacement in the
1696 address of a memory access in mode MODE. */
1699 rtx_ok_for_offset_p (enum machine_mode mode
, rtx op
)
1701 if (!CONST_INT_P (op
) || INTVAL (op
) < 0)
1707 return INTVAL (op
) <= 31;
1710 return (INTVAL (op
) % 2) == 0 && INTVAL (op
) < 63;
1714 return (INTVAL (op
) % 4) == 0 && INTVAL (op
) < 127;
1718 return (INTVAL (op
) % 4) == 0 && INTVAL (op
) < 123;
1725 /* Return whether X is a legitimate memory address for a memory operand
1728 Legitimate addresses are defined in two variants: a strict variant
1729 and a non-strict one. The STRICT parameter chooses which variant
1730 is desired by the caller.
1732 The strict variant is used in the reload pass. It must be defined
1733 so that any pseudo-register that has not been allocated a hard
1734 register is considered a memory reference. This is because in
1735 contexts where some kind of register is required, a
1736 pseudo-register with no hard register must be rejected. For
1737 non-hard registers, the strict variant should look up the
1738 `reg_renumber' array; it should then proceed using the hard
1739 register number in the array, or treat the pseudo as a memory
1740 reference if the array holds `-1'.
1742 The non-strict variant is used in other passes. It must be
1743 defined to accept all pseudo-registers in every context where some
1744 kind of register is required. */
1747 visium_legitimate_address_p (enum machine_mode mode
, rtx x
, bool strict
)
1752 /* If X is base+disp, check that we have an appropriate offset. */
1753 if (GET_CODE (x
) == PLUS
)
1755 if (!rtx_ok_for_offset_p (mode
, XEXP (x
, 1)))
1762 /* Now check the base: it must be either a register or a subreg thereof. */
1763 if (GET_CODE (base
) == SUBREG
)
1764 base
= SUBREG_REG (base
);
1768 regno
= REGNO (base
);
1770 /* For the strict variant, the register must be REGNO_OK_FOR_BASE_P. */
1772 return REGNO_OK_FOR_BASE_P (regno
);
1774 /* For the non-strict variant, the register may also be a pseudo. */
1775 return BASE_REGISTER_P (regno
) || regno
>= FIRST_PSEUDO_REGISTER
;
1778 /* Try machine-dependent ways of modifying an illegitimate address
1779 to be legitimate. If we find one, return the new, valid address.
1780 This macro is used in only one place: `memory_address' in explow.c.
1782 OLDX is the address as it was before break_out_memory_refs was called.
1783 In some cases it is useful to look at this to decide what needs to be done.
1785 MODE and WIN are passed so that this macro can use
1786 GO_IF_LEGITIMATE_ADDRESS.
1788 It is always safe for this macro to do nothing. It exists to recognize
1789 opportunities to optimize the output.
1793 memory (reg + <out of range int>)
1797 base_int = <out of range int> & ~mask
1798 ptr_reg = reg + base_int
1799 memory (ptr_reg + <out of range int> - base_int)
1801 Thus ptr_reg is a base register for a range of addresses,
1802 which should help CSE.
1804 For a 1 byte reference mask is 0x1f
1805 for a 2 byte reference mask is 0x3f
1806 For a 4 byte reference mask is 0x7f
1808 This reflects the indexing range of the processor.
1810 For a > 4 byte reference the mask is 0x7f provided all of the words
1811 can be accessed with the base address obtained. Otherwise a mask
1814 On rare occasions an unaligned base register value with an
1815 unaligned offset is generated. Unaligned offsets are left alone for
1819 visium_legitimize_address (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
1820 enum machine_mode mode
)
1822 if (GET_CODE (x
) == PLUS
1823 && GET_CODE (XEXP (x
, 1)) == CONST_INT
1824 && GET_CODE (XEXP (x
, 0)) == REG
&& mode
!= BLKmode
)
1826 int offset
= INTVAL (XEXP (x
, 1));
1827 int size
= GET_MODE_SIZE (mode
);
1828 int mask
= (size
== 1 ? 0x1f : (size
== 2 ? 0x3f : 0x7f));
1829 int mask1
= (size
== 1 ? 0 : (size
== 2 ? 1 : 3));
1830 int offset_base
= offset
& ~mask
;
1832 /* Check that all of the words can be accessed. */
1833 if (4 < size
&& 0x80 < size
+ offset
- offset_base
)
1834 offset_base
= offset
& ~0x3f;
1835 if (offset_base
!= 0 && offset_base
!= offset
&& (offset
& mask1
) == 0)
1837 rtx ptr_reg
= force_reg (Pmode
,
1838 gen_rtx_PLUS (Pmode
,
1840 GEN_INT (offset_base
)));
1842 return plus_constant (Pmode
, ptr_reg
, offset
- offset_base
);
1849 /* Perform a similar function to visium_legitimize_address, but this time
1850 for reload. Generating new registers is not an option here. Parts
1851 that need reloading are indicated by calling push_reload. */
1854 visium_legitimize_reload_address (rtx x
, enum machine_mode mode
, int opnum
,
1855 int type
, int ind ATTRIBUTE_UNUSED
)
1857 rtx newrtx
, tem
= NULL_RTX
;
1859 if (mode
== BLKmode
)
1862 if (optimize
&& GET_CODE (x
) == PLUS
)
1863 tem
= simplify_binary_operation (PLUS
, GET_MODE (x
), XEXP (x
, 0),
1866 newrtx
= tem
? tem
: x
;
1867 if (GET_CODE (newrtx
) == PLUS
1868 && GET_CODE (XEXP (newrtx
, 1)) == CONST_INT
1869 && GET_CODE (XEXP (newrtx
, 0)) == REG
1870 && BASE_REGISTER_P (REGNO (XEXP (newrtx
, 0))))
1872 int offset
= INTVAL (XEXP (newrtx
, 1));
1873 int size
= GET_MODE_SIZE (mode
);
1874 int mask
= (size
== 1 ? 0x1f : (size
== 2 ? 0x3f : 0x7f));
1875 int mask1
= (size
== 1 ? 0 : (size
== 2 ? 1 : 3));
1876 int offset_base
= offset
& ~mask
;
1878 /* Check that all of the words can be accessed. */
1879 if (4 < size
&& 0x80 < size
+ offset
- offset_base
)
1880 offset_base
= offset
& ~0x3f;
1882 if (offset_base
&& (offset
& mask1
) == 0)
1884 rtx temp
= gen_rtx_PLUS (Pmode
,
1885 XEXP (newrtx
, 0), GEN_INT (offset_base
));
1887 x
= gen_rtx_PLUS (Pmode
, temp
, GEN_INT (offset
- offset_base
));
1888 push_reload (XEXP (x
, 0), 0, &XEXP (x
, 0), 0,
1889 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
,
1890 (enum reload_type
) type
);
1898 /* Return the cost of moving data of mode MODE from a register in class FROM to
1899 one in class TO. A value of 2 is the default; other values are interpreted
1900 relative to that. */
1903 visium_register_move_cost (enum machine_mode mode
, reg_class_t from
,
1906 const int numwords
= (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
) ? 1 : 2;
1908 if (from
== MDB
|| to
== MDB
)
1910 else if (from
== MDC
|| to
== MDC
|| (from
== FP_REGS
) != (to
== FP_REGS
))
1911 return 4 * numwords
;
1913 return 2 * numwords
;
1916 /* Return the cost of moving data of mode MODE between a register of class
1917 CLASS and memory. IN is zero if the value is to be written to memory,
1918 non-zero if it is to be read in. This cost is relative to those in
1919 visium_register_move_cost. */
1922 visium_memory_move_cost (enum machine_mode mode
,
1923 reg_class_t to ATTRIBUTE_UNUSED
,
1926 /* Moving data in can be from PROM and this is expensive. */
1929 if (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
)
1935 /* Moving data out is mostly to RAM and should be cheaper. */
1938 if (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
)
1945 /* Return the relative costs of expression X. */
1948 visium_rtx_costs (rtx x
, machine_mode mode
, int outer_code ATTRIBUTE_UNUSED
,
1949 int opno ATTRIBUTE_UNUSED
, int *total
,
1950 bool speed ATTRIBUTE_UNUSED
)
1952 int code
= GET_CODE (x
);
1957 /* Small integers are as cheap as registers. 4-byte values can
1958 be fetched as immediate constants - let's give that the cost
1959 of an extra insn. */
1960 *total
= COSTS_N_INSNS (!satisfies_constraint_J (x
));
1966 *total
= COSTS_N_INSNS (2);
1972 split_double (x
, &high
, &low
);
1975 (!satisfies_constraint_J (high
) + !satisfies_constraint_J (low
));
1980 *total
= COSTS_N_INSNS (3);
1988 *total
= COSTS_N_INSNS (64);
1990 *total
= COSTS_N_INSNS (32);
1996 /* DImode operations are performed directly on the ALU. */
1998 *total
= COSTS_N_INSNS (2);
2000 *total
= COSTS_N_INSNS (1);
2006 /* DImode operations are performed on the EAM instead. */
2008 *total
= COSTS_N_INSNS (3);
2010 *total
= COSTS_N_INSNS (1);
2014 /* This matches the btst pattern. */
2015 if (GET_CODE (XEXP (x
, 0)) == ZERO_EXTRACT
2016 && XEXP (x
, 1) == const0_rtx
2017 && XEXP (XEXP (x
, 0), 1) == const1_rtx
2018 && satisfies_constraint_K (XEXP (XEXP (x
, 0), 2)))
2019 *total
= COSTS_N_INSNS (1);
2027 /* Split a double move of OPERANDS in MODE. */
2030 visium_split_double_move (rtx
*operands
, enum machine_mode mode
)
2034 /* Check register to register with overlap. */
2035 if (GET_CODE (operands
[0]) == REG
2036 && GET_CODE (operands
[1]) == REG
2037 && REGNO (operands
[0]) == REGNO (operands
[1]) + 1)
2040 /* Check memory to register where the base reg overlaps the destination. */
2041 if (GET_CODE (operands
[0]) == REG
&& GET_CODE (operands
[1]) == MEM
)
2043 rtx op
= XEXP (operands
[1], 0);
2045 if (GET_CODE (op
) == SUBREG
)
2046 op
= SUBREG_REG (op
);
2048 if (GET_CODE (op
) == REG
&& REGNO (op
) == REGNO (operands
[0]))
2051 if (GET_CODE (op
) == PLUS
)
2053 rtx x
= XEXP (op
, 0);
2054 rtx y
= XEXP (op
, 1);
2056 if (GET_CODE (x
) == REG
&& REGNO (x
) == REGNO (operands
[0]))
2059 if (GET_CODE (y
) == REG
&& REGNO (y
) == REGNO (operands
[0]))
2066 operands
[2] = operand_subword (operands
[0], 1, 1, mode
);
2067 operands
[3] = operand_subword (operands
[1], 1, 1, mode
);
2068 operands
[4] = operand_subword (operands
[0], 0, 1, mode
);
2069 operands
[5] = operand_subword (operands
[1], 0, 1, mode
);
2073 operands
[2] = operand_subword (operands
[0], 0, 1, mode
);
2074 operands
[3] = operand_subword (operands
[1], 0, 1, mode
);
2075 operands
[4] = operand_subword (operands
[0], 1, 1, mode
);
2076 operands
[5] = operand_subword (operands
[1], 1, 1, mode
);
2080 /* Split a double addition or subtraction of operands. */
2083 visium_split_double_add (enum rtx_code code
, rtx op0
, rtx op1
, rtx op2
)
2085 rtx op3
= gen_lowpart (SImode
, op0
);
2086 rtx op4
= gen_lowpart (SImode
, op1
);
2088 rtx op6
= gen_highpart (SImode
, op0
);
2089 rtx op7
= (op1
== const0_rtx
? op1
: gen_highpart (SImode
, op1
));
2093 /* If operand #2 is a small constant, then its high part is null. */
2094 if (CONST_INT_P (op2
))
2096 HOST_WIDE_INT val
= INTVAL (op2
);
2100 code
= (code
== MINUS
? PLUS
: MINUS
);
2104 op5
= gen_int_mode (val
, SImode
);
2109 op5
= gen_lowpart (SImode
, op2
);
2110 op8
= gen_highpart (SImode
, op2
);
2113 /* This is the {add,sub,neg}si3_insn_set_flags pattern. */
2114 if (op4
== const0_rtx
)
2115 x
= gen_rtx_NEG (SImode
, op5
);
2117 x
= gen_rtx_fmt_ee (code
, SImode
, op4
, op5
);
2118 pat
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (2));
2119 XVECEXP (pat
, 0, 0) = gen_rtx_SET (op3
, x
);
2120 flags
= gen_rtx_REG (CC_NOOVmode
, FLAGS_REGNUM
);
2121 x
= gen_rtx_COMPARE (CC_NOOVmode
, shallow_copy_rtx (x
), const0_rtx
);
2122 XVECEXP (pat
, 0, 1) = gen_rtx_SET (flags
, x
);
2125 /* This is the plus_[plus_]sltu_flags or minus_[minus_]sltu_flags pattern. */
2126 if (op8
== const0_rtx
)
2129 x
= gen_rtx_fmt_ee (code
, SImode
, op7
, op8
);
2130 x
= gen_rtx_fmt_ee (code
, SImode
, x
, gen_rtx_LTU (SImode
, flags
, const0_rtx
));
2131 pat
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (2));
2132 XVECEXP (pat
, 0, 0) = gen_rtx_SET (op6
, x
);
2133 flags
= gen_rtx_REG (CCmode
, FLAGS_REGNUM
);
2134 XVECEXP (pat
, 0, 1) = gen_rtx_CLOBBER (VOIDmode
, flags
);
2137 visium_flags_exposed
= true;
2140 /* Expand a copysign of OPERANDS in MODE. */
2143 visium_expand_copysign (rtx
*operands
, enum machine_mode mode
)
2145 rtx op0
= operands
[0];
2146 rtx op1
= operands
[1];
2147 rtx op2
= operands
[2];
2148 rtx mask
= force_reg (SImode
, GEN_INT (0x7fffffff));
2151 /* We manually handle SFmode because the abs and neg instructions of
2152 the FPU on the MCM have a non-standard behavior wrt NaNs. */
2153 gcc_assert (mode
== SFmode
);
2155 /* First get all the non-sign bits of op1. */
2156 if (GET_CODE (op1
) == CONST_DOUBLE
)
2158 if (real_isneg (CONST_DOUBLE_REAL_VALUE (op1
)))
2159 op1
= simplify_unary_operation (ABS
, mode
, op1
, mode
);
2160 if (op1
!= CONST0_RTX (mode
))
2163 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op1
), l
);
2164 op1
= force_reg (SImode
, gen_int_mode (l
, SImode
));
2169 op1
= copy_to_mode_reg (SImode
, gen_lowpart (SImode
, op1
));
2170 op1
= force_reg (SImode
, gen_rtx_AND (SImode
, op1
, mask
));
2173 /* Then get the sign bit of op2. */
2174 mask
= force_reg (SImode
, gen_rtx_NOT (SImode
, mask
));
2175 op2
= copy_to_mode_reg (SImode
, gen_lowpart (SImode
, op2
));
2176 op2
= force_reg (SImode
, gen_rtx_AND (SImode
, op2
, mask
));
2178 /* Finally OR the two values. */
2179 if (op1
== CONST0_RTX (SFmode
))
2182 x
= force_reg (SImode
, gen_rtx_IOR (SImode
, op1
, op2
));
2184 /* And move the result to the destination. */
2185 emit_insn (gen_rtx_SET (op0
, gen_lowpart (SFmode
, x
)));
2188 /* Expand a cstore of OPERANDS in MODE for EQ/NE/LTU/GTU/GEU/LEU. We generate
2189 the result in the C flag and use the ADC/SUBC instructions to write it into
2190 the destination register.
2192 It would also be possible to implement support for LT/GT/LE/GE by means of
2193 the RFLAG instruction followed by some shifts, but this can pessimize the
2197 visium_expand_int_cstore (rtx
*operands
, enum machine_mode mode
)
2199 enum rtx_code code
= GET_CODE (operands
[1]);
2200 rtx op0
= operands
[0], op1
= operands
[2], op2
= operands
[3], sltu
;
2201 bool reverse
= false;
2207 /* We use a special comparison to get the result in the C flag. */
2208 if (op2
!= const0_rtx
)
2209 op1
= force_reg (mode
, gen_rtx_XOR (mode
, op1
, op2
));
2210 op1
= gen_rtx_NOT (mode
, op1
);
2218 /* The result is naturally in the C flag modulo a couple of tricks. */
2219 code
= reverse_condition (code
);
2222 /* ... fall through ... */
2238 /* We need either a single ADC or a SUBC and a PLUS. */
2239 sltu
= gen_rtx_LTU (SImode
, op1
, op2
);
2243 rtx tmp
= copy_to_mode_reg (SImode
, gen_rtx_NEG (SImode
, sltu
));
2244 emit_insn (gen_add3_insn (op0
, tmp
, const1_rtx
));
2247 emit_insn (gen_rtx_SET (op0
, sltu
));
2250 /* Expand a cstore of OPERANDS in MODE for LT/GT/UNGE/UNLE. We generate the
2251 result in the C flag and use the ADC/SUBC instructions to write it into
2252 the destination register. */
2255 visium_expand_fp_cstore (rtx
*operands
,
2256 enum machine_mode mode ATTRIBUTE_UNUSED
)
2258 enum rtx_code code
= GET_CODE (operands
[1]);
2259 rtx op0
= operands
[0], op1
= operands
[2], op2
= operands
[3], slt
;
2260 bool reverse
= false;
2266 /* The result is naturally in the C flag modulo a couple of tricks. */
2267 code
= reverse_condition_maybe_unordered (code
);
2270 /* ... fall through ... */
2286 /* We need either a single ADC or a SUBC and a PLUS. */
2287 slt
= gen_rtx_LT (SImode
, op1
, op2
);
2291 rtx tmp
= copy_to_mode_reg (SImode
, gen_rtx_NEG (SImode
, slt
));
2292 emit_insn (gen_add3_insn (op0
, tmp
, const1_rtx
));
2295 emit_insn (gen_rtx_SET (op0
, slt
));
2298 /* Split a compare-and-store with CODE, operands OP2 and OP3, combined with
2299 operation with OP_CODE, operands OP0 and OP1. */
2302 visium_split_cstore (enum rtx_code op_code
, rtx op0
, rtx op1
,
2303 enum rtx_code code
, rtx op2
, rtx op3
)
2305 enum machine_mode cc_mode
= visium_select_cc_mode (code
, op2
, op3
);
2307 /* If a FP cstore was reversed, then it was originally UNGE/UNLE. */
2308 if (cc_mode
== CCFPEmode
&& (op_code
== NEG
|| op_code
== MINUS
))
2311 rtx flags
= gen_rtx_REG (cc_mode
, FLAGS_REGNUM
);
2312 rtx x
= gen_rtx_COMPARE (cc_mode
, op2
, op3
);
2313 x
= gen_rtx_SET (flags
, x
);
2316 x
= gen_rtx_fmt_ee (code
, SImode
, flags
, const0_rtx
);
2322 x
= gen_rtx_NEG (SImode
, x
);
2326 x
= gen_rtx_fmt_ee (op_code
, SImode
, op1
, x
);
2332 rtx pat
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (2));
2333 XVECEXP (pat
, 0, 0) = gen_rtx_SET (op0
, x
);
2334 flags
= gen_rtx_REG (CCmode
, FLAGS_REGNUM
);
2335 XVECEXP (pat
, 0, 1) = gen_rtx_CLOBBER (VOIDmode
, flags
);
2338 visium_flags_exposed
= true;
2341 /* Generate a call to a library function to move BYTES_RTX bytes from SRC with
2342 address SRC_REG to DST with address DST_REG in 4-byte chunks. */
2345 expand_block_move_4 (rtx dst
, rtx dst_reg
, rtx src
, rtx src_reg
, rtx bytes_rtx
)
2347 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2348 unsigned int rem
= bytes
% 4;
2355 emit_move_insn (regno_reg_rtx
[1], dst_reg
);
2356 emit_move_insn (regno_reg_rtx
[2], src_reg
);
2357 emit_move_insn (regno_reg_rtx
[3], bytes_rtx
);
2359 insn
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (8));
2360 XVECEXP (insn
, 0, 0)
2361 = gen_rtx_SET (replace_equiv_address_nv (dst
, regno_reg_rtx
[1]),
2362 replace_equiv_address_nv (src
, regno_reg_rtx
[2]));
2363 XVECEXP (insn
, 0, 1) = gen_rtx_USE (VOIDmode
, regno_reg_rtx
[3]);
2364 for (i
= 1; i
<= 6; i
++)
2365 XVECEXP (insn
, 0, 1 + i
)
2366 = gen_rtx_CLOBBER (VOIDmode
, regno_reg_rtx
[i
]);
2370 emit_library_call (long_int_memcpy_libfunc
, LCT_NORMAL
, VOIDmode
, 3,
2373 convert_to_mode (TYPE_MODE (sizetype
),
2374 GEN_INT (bytes
>> 2),
2375 TYPE_UNSIGNED (sizetype
)),
2376 TYPE_MODE (sizetype
));
2380 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2381 src
= replace_equiv_address_nv (src
, src_reg
);
2386 emit_move_insn (adjust_address_nv (dst
, HImode
, bytes
),
2387 adjust_address_nv (src
, HImode
, bytes
));
2393 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2394 adjust_address_nv (src
, QImode
, bytes
));
2397 /* Generate a call to a library function to move BYTES_RTX bytes from SRC with
2398 address SRC_REG to DST with address DST_REG in 2-bytes chunks. */
2401 expand_block_move_2 (rtx dst
, rtx dst_reg
, rtx src
, rtx src_reg
, rtx bytes_rtx
)
2403 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2404 unsigned int rem
= bytes
% 2;
2406 emit_library_call (wrd_memcpy_libfunc
, LCT_NORMAL
, VOIDmode
, 3,
2409 convert_to_mode (TYPE_MODE (sizetype
),
2410 GEN_INT (bytes
>> 1),
2411 TYPE_UNSIGNED (sizetype
)),
2412 TYPE_MODE (sizetype
));
2416 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2417 src
= replace_equiv_address_nv (src
, src_reg
);
2420 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2421 adjust_address_nv (src
, QImode
, bytes
));
2424 /* Generate a call to a library function to move BYTES_RTX bytes from address
2425 SRC_REG to address DST_REG in 1-byte chunks. */
2428 expand_block_move_1 (rtx dst_reg
, rtx src_reg
, rtx bytes_rtx
)
2430 emit_library_call (byt_memcpy_libfunc
, LCT_NORMAL
, VOIDmode
, 3,
2433 convert_to_mode (TYPE_MODE (sizetype
),
2435 TYPE_UNSIGNED (sizetype
)),
2436 TYPE_MODE (sizetype
));
2439 /* Generate a call to a library function to set BYTES_RTX bytes of DST with
2440 address DST_REG to VALUE_RTX in 4-byte chunks. */
2443 expand_block_set_4 (rtx dst
, rtx dst_reg
, rtx value_rtx
, rtx bytes_rtx
)
2445 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2446 unsigned int rem
= bytes
% 4;
2448 value_rtx
= convert_to_mode (Pmode
, value_rtx
, 1);
2449 emit_library_call (long_int_memset_libfunc
, LCT_NORMAL
, VOIDmode
, 3,
2452 convert_to_mode (TYPE_MODE (sizetype
),
2453 GEN_INT (bytes
>> 2),
2454 TYPE_UNSIGNED (sizetype
)),
2455 TYPE_MODE (sizetype
));
2459 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2464 if (CONST_INT_P (value_rtx
))
2466 const unsigned HOST_WIDE_INT value
= UINTVAL (value_rtx
) & 0xff;
2467 emit_move_insn (adjust_address_nv (dst
, HImode
, bytes
),
2468 gen_int_mode ((value
<< 8) | value
, HImode
));
2472 rtx temp
= convert_to_mode (QImode
, value_rtx
, 1);
2473 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
), temp
);
2474 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
+ 1), temp
);
2481 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2482 convert_to_mode (QImode
, value_rtx
, 1));
2485 /* Generate a call to a library function to set BYTES_RTX bytes of DST with
2486 address DST_REG to VALUE_RTX in 2-byte chunks. */
2489 expand_block_set_2 (rtx dst
, rtx dst_reg
, rtx value_rtx
, rtx bytes_rtx
)
2491 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2492 unsigned int rem
= bytes
% 2;
2494 value_rtx
= convert_to_mode (Pmode
, value_rtx
, 1);
2495 emit_library_call (wrd_memset_libfunc
, LCT_NORMAL
, VOIDmode
, 3,
2498 convert_to_mode (TYPE_MODE (sizetype
),
2499 GEN_INT (bytes
>> 1),
2500 TYPE_UNSIGNED (sizetype
)),
2501 TYPE_MODE (sizetype
));
2505 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2508 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2509 convert_to_mode (QImode
, value_rtx
, 1));
2512 /* Generate a call to a library function to set BYTES_RTX bytes at address
2513 DST_REG to VALUE_RTX in 1-byte chunks. */
2516 expand_block_set_1 (rtx dst_reg
, rtx value_rtx
, rtx bytes_rtx
)
2518 value_rtx
= convert_to_mode (Pmode
, value_rtx
, 1);
2519 emit_library_call (byt_memset_libfunc
, LCT_NORMAL
, VOIDmode
, 3,
2522 convert_to_mode (TYPE_MODE (sizetype
),
2524 TYPE_UNSIGNED (sizetype
)),
2525 TYPE_MODE (sizetype
));
2528 /* Expand string/block move operations.
2530 operands[0] is the pointer to the destination.
2531 operands[1] is the pointer to the source.
2532 operands[2] is the number of bytes to move.
2533 operands[3] is the alignment.
2535 Return 1 upon success, 0 otherwise. */
2538 visium_expand_block_move (rtx
*operands
)
2540 rtx dst
= operands
[0];
2541 rtx src
= operands
[1];
2542 rtx bytes_rtx
= operands
[2];
2543 rtx align_rtx
= operands
[3];
2544 const int align
= INTVAL (align_rtx
);
2545 rtx dst_reg
, src_reg
;
2546 tree dst_expr
, src_expr
;
2548 /* We only handle a fixed number of bytes for now. */
2549 if (!CONST_INT_P (bytes_rtx
) || INTVAL (bytes_rtx
) <= 0)
2552 /* Copy the addresses into scratch registers. */
2553 dst_reg
= copy_addr_to_reg (XEXP (dst
, 0));
2554 src_reg
= copy_addr_to_reg (XEXP (src
, 0));
2556 /* Move the data with the appropriate granularity. */
2558 expand_block_move_4 (dst
, dst_reg
, src
, src_reg
, bytes_rtx
);
2559 else if (align
>= 2)
2560 expand_block_move_2 (dst
, dst_reg
, src
, src_reg
, bytes_rtx
);
2562 expand_block_move_1 (dst_reg
, src_reg
, bytes_rtx
);
2564 /* Since DST and SRC are passed to a libcall, mark the corresponding
2565 tree EXPR as addressable. */
2566 dst_expr
= MEM_EXPR (dst
);
2567 src_expr
= MEM_EXPR (src
);
2569 mark_addressable (dst_expr
);
2571 mark_addressable (src_expr
);
2576 /* Expand string/block set operations.
2578 operands[0] is the pointer to the destination.
2579 operands[1] is the number of bytes to set.
2580 operands[2] is the source value.
2581 operands[3] is the alignment.
2583 Return 1 upon success, 0 otherwise. */
2586 visium_expand_block_set (rtx
*operands
)
2588 rtx dst
= operands
[0];
2589 rtx bytes_rtx
= operands
[1];
2590 rtx value_rtx
= operands
[2];
2591 rtx align_rtx
= operands
[3];
2592 const int align
= INTVAL (align_rtx
);
2596 /* We only handle a fixed number of bytes for now. */
2597 if (!CONST_INT_P (bytes_rtx
) || INTVAL (bytes_rtx
) <= 0)
2600 /* Copy the address into a scratch register. */
2601 dst_reg
= copy_addr_to_reg (XEXP (dst
, 0));
2603 /* Set the data with the appropriate granularity. */
2605 expand_block_set_4 (dst
, dst_reg
, value_rtx
, bytes_rtx
);
2606 else if (align
>= 2)
2607 expand_block_set_2 (dst
, dst_reg
, value_rtx
, bytes_rtx
);
2609 expand_block_set_1 (dst_reg
, value_rtx
, bytes_rtx
);
2611 /* Since DST is passed to a libcall, mark the corresponding
2612 tree EXPR as addressable. */
2613 dst_expr
= MEM_EXPR (dst
);
2615 mark_addressable (dst_expr
);
2620 /* Initialize a trampoline. M_TRAMP is an RTX for the memory block for the
2621 trampoline, FNDECL is the FUNCTION_DECL for the nested function and
2622 STATIC_CHAIN is an RTX for the static chain value that should be passed
2623 to the function when it is called. */
2626 visium_trampoline_init (rtx m_tramp
, tree fndecl
, rtx static_chain
)
2628 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2629 rtx addr
= XEXP (m_tramp
, 0);
2631 /* The trampoline initialization sequence is:
2633 moviu r9,%u FUNCTION
2634 movil r9,%l FUNCTION
2639 We don't use r0 as the destination register of the branch because we want
2640 the Branch Pre-decode Logic of the GR6 to use the Address Load Array to
2641 predict the branch target. */
2643 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 0)),
2644 plus_constant (SImode
,
2645 expand_shift (RSHIFT_EXPR
, SImode
, fnaddr
,
2649 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 4)),
2650 plus_constant (SImode
,
2651 expand_and (SImode
, fnaddr
, GEN_INT (0xffff),
2655 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 8)),
2656 plus_constant (SImode
,
2657 expand_shift (RSHIFT_EXPR
, SImode
,
2662 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 12)),
2663 gen_int_mode (0xff892404, SImode
));
2665 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 16)),
2666 plus_constant (SImode
,
2667 expand_and (SImode
, static_chain
,
2668 GEN_INT (0xffff), NULL_RTX
),
2671 emit_library_call (set_trampoline_parity_libfunc
, LCT_NORMAL
, VOIDmode
, 1,
2675 /* Return true if the current function must have and use a frame pointer. */
2678 visium_frame_pointer_required (void)
2680 /* The frame pointer is required if the function isn't leaf to be able to
2681 do manual stack unwinding. */
2685 /* If the stack pointer is dynamically modified in the function, it cannot
2686 serve as the frame pointer. */
2687 if (!crtl
->sp_is_unchanging
)
2690 /* If the function receives nonlocal gotos, it needs to save the frame
2691 pointer in the nonlocal_goto_save_area object. */
2692 if (cfun
->has_nonlocal_label
)
2695 /* The frame also needs to be established in some special cases. */
2696 if (visium_frame_needed
)
2702 /* Profiling support. Just a call to MCOUNT is needed. No labelled counter
2703 location is involved. Proper support for __builtin_return_address is also
2704 required, which is fairly straightforward provided a frame gets created. */
2707 visium_profile_hook (void)
2709 visium_frame_needed
= true;
2710 emit_library_call (gen_rtx_SYMBOL_REF (Pmode
, "mcount"), LCT_NORMAL
,
2714 /* A C expression whose value is RTL representing the address in a stack frame
2715 where the pointer to the caller's frame is stored. Assume that FRAMEADDR is
2716 an RTL expression for the address of the stack frame itself.
2718 If you don't define this macro, the default is to return the value of
2719 FRAMEADDR--that is, the stack frame address is also the address of the stack
2720 word that points to the previous frame. */
2723 visium_dynamic_chain_address (rtx frame
)
2725 /* This is the default, but we need to make sure the frame gets created. */
2726 visium_frame_needed
= true;
2730 /* A C expression whose value is RTL representing the value of the return
2731 address for the frame COUNT steps up from the current frame, after the
2732 prologue. FRAMEADDR is the frame pointer of the COUNT frame, or the frame
2733 pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' is
2736 The value of the expression must always be the correct address when COUNT is
2737 zero, but may be `NULL_RTX' if there is not way to determine the return
2738 address of other frames. */
2741 visium_return_addr_rtx (int count
, rtx frame ATTRIBUTE_UNUSED
)
2743 /* Dont try to compute anything other than frame zero. */
2747 visium_frame_needed
= true;
2749 gen_frame_mem (Pmode
, plus_constant (Pmode
, hard_frame_pointer_rtx
, 4));
2752 /* Helper function for EH_RETURN_HANDLER_RTX. Return the RTX representing a
2753 location in which to store the address of an exception handler to which we
2757 visium_eh_return_handler_rtx (void)
2760 = gen_frame_mem (SImode
, plus_constant (Pmode
, hard_frame_pointer_rtx
, 4));
2761 MEM_VOLATILE_P (mem
) = 1;
2765 static struct machine_function
*
2766 visium_init_machine_status (void)
2768 return ggc_cleared_alloc
<machine_function
> ();
2771 /* The per-function data machinery is needed to indicate when a frame
2775 visium_init_expanders (void)
2777 init_machine_status
= visium_init_machine_status
;
2780 /* Given a comparison code (EQ, NE, etc.) and the operands of a COMPARE,
2781 return the mode to be used for the comparison. */
2784 visium_select_cc_mode (enum rtx_code code
, rtx op0
, rtx op1
)
2786 if (GET_MODE_CLASS (GET_MODE (op0
)) == MODE_FLOAT
)
2806 /* These 2 comparison codes are not supported. */
2814 if (op1
!= const0_rtx
)
2817 switch (GET_CODE (op0
))
2825 /* The V flag may be set differently from a COMPARE with zero.
2826 The consequence is that a comparison operator testing V must
2827 be turned into another operator not testing V and yielding
2828 the same result for a comparison with zero. That's possible
2829 for GE/LT which become NC/NS respectively, but not for GT/LE
2830 for which the altered operator doesn't exist on the Visium. */
2834 /* This is a btst, the result is in C instead of Z. */
2838 /* This is a degenerate case, typically an uninitialized variable. */
2839 gcc_assert (op0
== constm1_rtx
);
2849 /* Pretend that the flags are set as for a COMPARE with zero.
2850 That's mostly true, except for the 2 right shift insns that
2851 will set the C flag. But the C flag is relevant only for
2852 the unsigned comparison operators and they are eliminated
2853 when applied to a comparison with zero. */
2861 /* Split a compare-and-branch with CODE, operands OP0 and OP1, and LABEL. */
2864 visium_split_cbranch (enum rtx_code code
, rtx op0
, rtx op1
, rtx label
)
2866 enum machine_mode cc_mode
= visium_select_cc_mode (code
, op0
, op1
);
2867 rtx flags
= gen_rtx_REG (cc_mode
, FLAGS_REGNUM
);
2869 rtx x
= gen_rtx_COMPARE (cc_mode
, op0
, op1
);
2870 x
= gen_rtx_SET (flags
, x
);
2873 x
= gen_rtx_fmt_ee (code
, VOIDmode
, flags
, const0_rtx
);
2874 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
, gen_rtx_LABEL_REF (Pmode
, label
),
2876 x
= gen_rtx_SET (pc_rtx
, x
);
2879 visium_flags_exposed
= true;
2882 /* Branch instructions on the Visium.
2884 Setting aside the interrupt-handling specific instructions, the ISA has
2885 two branch instructions: BRR and BRA. The former is used to implement
2886 short branches (+/- 2^17) within functions and its target is encoded in
2887 the instruction. The latter is used to implement all the other types
2888 of control flow changes and its target might not be statically known
2889 or even easily predictable at run time. Here's a complete summary of
2890 the patterns that generate a BRA instruction:
2900 Among these patterns, only the return (5) and the long branch (6) can be
2901 conditional; all the other patterns are always unconditional.
2903 The following algorithm can be used to identify the pattern for which
2904 the BRA instruction was generated and work out its target:
2906 A. If the source is r21 and the destination is r0, this is a return (5)
2907 and the target is the caller (i.e. the value of r21 on function's
2910 B. If the source is rN, N != 21 and the destination is r0, this is either
2911 an indirect jump or a table jump (1, 2) and the target is not easily
2914 C. If the source is rN, N != 21 and the destination is r21, this is a call
2915 (3) and the target is given by the preceding MOVIL/MOVIU pair for rN,
2916 unless this is an indirect call in which case the target is not easily
2919 D. If the source is rN, N != 21 and the destination is also rN, this is
2920 either a sibling call or a trampoline (4, 7) and the target is given
2921 by the preceding MOVIL/MOVIU pair for rN.
2923 E. If the source is r21 and the destination is also r21, this is a long
2924 branch (6) and the target is given by the preceding MOVIL/MOVIU pair
2927 The other combinations are not used. This implementation has been devised
2928 to accommodate the branch predictor of the GR6 but is used unconditionally
2929 by the compiler, i.e. including for earlier processors. */
2931 /* Output a conditional/unconditional branch to LABEL. COND is the string
2932 condition. INSN is the instruction. */
2935 output_branch (rtx label
, const char *cond
, rtx_insn
*insn
)
2941 operands
[0] = label
;
2943 /* If the length of the instruction is greater than 8, then this is a
2944 long branch and we need to work harder to emit it properly. */
2945 if (get_attr_length (insn
) > 8)
2949 /* If the link register has been saved, then we use it. */
2950 if (current_function_saves_lr ())
2952 operands
[1] = regno_reg_rtx
[LINK_REGNUM
];
2956 /* Or else, if the long-branch register isn't live, we use it. */
2957 else if (!df_regs_ever_live_p (long_branch_regnum
))
2959 operands
[1] = regno_reg_rtx
[long_branch_regnum
];
2963 /* Otherwise, we will use the long-branch register but we need to
2964 spill it to the stack and reload it at the end. We should have
2965 reserved the LR slot for this purpose. */
2968 operands
[1] = regno_reg_rtx
[long_branch_regnum
];
2970 gcc_assert (current_function_has_lr_slot ());
2973 /* First emit the spill to the stack:
2976 write.l [1](sp),reg */
2981 rtx_insn
*delay
= NEXT_INSN (insn
);
2985 final_scan_insn (delay
, asm_out_file
, optimize
, 0, &seen
);
2986 PATTERN (delay
) = gen_blockage ();
2987 INSN_CODE (delay
) = -1;
2990 if (current_function_saves_fp ())
2991 output_asm_insn ("write.l 1(sp),%1", operands
);
2993 output_asm_insn ("write.l (sp),%1", operands
);
2996 /* Then emit the core sequence:
3002 We don't use r0 as the destination register of the branch because we
3003 want the Branch Pre-decode Logic of the GR6 to use the Address Load
3004 Array to predict the branch target. */
3005 output_asm_insn ("moviu %1,%%u %0", operands
);
3006 output_asm_insn ("movil %1,%%l %0", operands
);
3007 strcpy (str
, "bra ");
3009 strcat (str
, ",%1,%1");
3012 strcat (str
, "\t\t;long branch");
3013 output_asm_insn (str
, operands
);
3015 /* Finally emit the reload:
3017 read.l reg,[1](sp) */
3020 if (current_function_saves_fp ())
3021 output_asm_insn (" read.l %1,1(sp)", operands
);
3023 output_asm_insn (" read.l %1,(sp)", operands
);
3027 /* Or else, if the label is PC, then this is a return. */
3028 else if (label
== pc_rtx
)
3030 strcpy (str
, "bra ");
3032 strcat (str
, ",r21,r0%#\t\t;return");
3033 output_asm_insn (str
, operands
);
3036 /* Otherwise, this is a short branch. */
3039 strcpy (str
, "brr ");
3041 strcat (str
, ",%0%#");
3042 output_asm_insn (str
, operands
);
3048 /* Output an unconditional branch to LABEL. INSN is the instruction. */
3051 output_ubranch (rtx label
, rtx_insn
*insn
)
3053 return output_branch (label
, "tr", insn
);
3056 /* Output a conditional branch to LABEL. CODE is the comparison code.
3057 CC_MODE is the mode of the CC register. REVERSED is non-zero if we
3058 should reverse the sense of the comparison. INSN is the instruction. */
3061 output_cbranch (rtx label
, enum rtx_code code
, enum machine_mode cc_mode
,
3062 int reversed
, rtx_insn
*insn
)
3068 if (cc_mode
== CCFPmode
|| cc_mode
== CCFPEmode
)
3069 code
= reverse_condition_maybe_unordered (code
);
3071 code
= reverse_condition (code
);
3077 if (cc_mode
== CC_BTSTmode
)
3084 if (cc_mode
== CC_BTSTmode
)
3091 if (cc_mode
== CC_NOOVmode
)
3102 if (cc_mode
== CCFPmode
|| cc_mode
== CCFPEmode
)
3109 if (cc_mode
== CCFPmode
|| cc_mode
== CCFPEmode
)
3111 else if (cc_mode
== CC_NOOVmode
)
3157 /* These 2 comparison codes are not supported. */
3164 return output_branch (label
, cond
, insn
);
3167 /* Implement TARGET_PRINT_OPERAND_PUNCT_VALID_P. */
3170 visium_print_operand_punct_valid_p (unsigned char code
)
3175 /* Implement TARGET_PRINT_OPERAND. Output to stdio stream FILE the assembler
3176 syntax for an instruction operand OP subject to the modifier LETTER. */
3179 visium_print_operand (FILE *file
, rtx op
, int letter
)
3184 /* Output an insn in a delay slot. */
3186 visium_indent_opcode
= 1;
3188 fputs ("\n\t nop", file
);
3192 /* Print LS 8 bits of operand. */
3193 fprintf (file
, HOST_WIDE_INT_PRINT_UNSIGNED
, UINTVAL (op
) & 0xff);
3197 /* Print LS 16 bits of operand. */
3198 fprintf (file
, HOST_WIDE_INT_PRINT_UNSIGNED
, UINTVAL (op
) & 0xffff);
3202 /* Print MS 16 bits of operand. */
3204 HOST_WIDE_INT_PRINT_UNSIGNED
, (UINTVAL (op
) >> 16) & 0xffff);
3208 /* It's either a register or zero. */
3209 if (GET_CODE (op
) == REG
)
3210 fputs (reg_names
[REGNO (op
)], file
);
3212 fputs (reg_names
[0], file
);
3216 /* It's either a FP register or zero. */
3217 if (GET_CODE (op
) == REG
)
3218 fputs (reg_names
[REGNO (op
)], file
);
3220 fputs (reg_names
[FP_FIRST_REGNUM
], file
);
3224 switch (GET_CODE (op
))
3228 fputs (reg_names
[REGNO (op
) + 1], file
);
3230 fputs (reg_names
[REGNO (op
)], file
);
3236 output_addr_const (file
, op
);
3240 visium_print_operand_address (file
, GET_MODE (op
), XEXP (op
, 0));
3244 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (op
));
3248 asm_fprintf (file
, "%LL%d", CODE_LABEL_NUMBER (op
));
3252 visium_print_operand (file
, XEXP (op
, 1), letter
);
3256 fatal_insn ("illegal operand ", op
);
3260 /* Implement TARGET_PRINT_OPERAND_ADDRESS. Output to stdio stream FILE the
3261 assembler syntax for an instruction operand that is a memory reference
3262 whose address is ADDR. */
3265 visium_print_operand_address (FILE *file
, enum machine_mode mode
, rtx addr
)
3267 switch (GET_CODE (addr
))
3271 fprintf (file
, "(%s)", reg_names
[true_regnum (addr
)]);
3276 rtx x
= XEXP (addr
, 0), y
= XEXP (addr
, 1);
3278 switch (GET_CODE (x
))
3282 if (CONST_INT_P (y
))
3284 unsigned int regno
= true_regnum (x
);
3285 HOST_WIDE_INT val
= INTVAL (y
);
3303 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
"(%s)", val
,
3307 fatal_insn ("illegal operand address (1)", addr
);
3311 if (CONSTANT_P (x
) && CONSTANT_P (y
))
3312 output_addr_const (file
, addr
);
3314 fatal_insn ("illegal operand address (2)", addr
);
3324 output_addr_const (file
, addr
);
3328 if (NOTE_KIND (addr
) != NOTE_INSN_DELETED_LABEL
)
3329 fatal_insn ("illegal operand address (3)", addr
);
3333 asm_fprintf (file
, "%LL%d", CODE_LABEL_NUMBER (addr
));
3337 fatal_insn ("illegal operand address (4)", addr
);
3342 /* The Visium stack frames look like:
3344 Before call After call
3345 +-----------------------+ +-----------------------+
3347 high | previous | | previous |
3348 mem | frame | | frame |
3350 +-----------------------+ +-----------------------+
3352 | arguments on stack | | arguments on stack |
3354 SP+0->+-----------------------+ +-----------------------+
3355 | reg parm save area, |
3356 | only created for |
3357 | variable argument |
3359 +-----------------------+
3361 | register save area |
3363 +-----------------------+
3367 FP+8->+-----------------------+
3369 FP+4->+-----------------------+
3371 FP+0->+-----------------------+
3373 | alloca allocations |
3375 +-----------------------+
3377 low | arguments on stack |
3379 SP+0->+-----------------------+
3382 1) The "reg parm save area" does not exist for non variable argument fns.
3383 2) The FP register is not saved if `frame_pointer_needed' is zero and it
3384 is not altered in the current function.
3385 3) The return address is not saved if there is no frame pointer and the
3386 current function is leaf.
3387 4) If the return address is not saved and the static chain register is
3388 live in the function, we allocate the return address slot to be able
3389 to spill the register for a long branch. */
3391 /* Define the register classes for local purposes. */
3392 enum reg_type
{ general
, mdb
, mdc
, floating
, last_type
};
3394 #define GET_REG_TYPE(regno) \
3395 (GP_REGISTER_P (regno) ? general : \
3396 (regno) == MDB_REGNUM ? mdb : \
3397 (regno) == MDC_REGNUM ? mdc : \
3400 /* First regno of each register type. */
3401 const int first_regno
[last_type
] = {0, MDB_REGNUM
, MDC_REGNUM
, FP_FIRST_REGNUM
};
3403 /* Size in bytes of each register type. */
3404 const int reg_type_size
[last_type
] = {4, 8, 4, 4};
3406 /* Structure to be filled in by visium_compute_frame_size. */
3407 struct visium_frame_info
3409 unsigned int save_area_size
; /* # bytes in the reg parm save area. */
3410 unsigned int reg_size1
; /* # bytes to store first block of regs. */
3411 unsigned int reg_size2
; /* # bytes to store second block of regs. */
3412 unsigned int max_reg1
; /* max. regno in first block */
3413 unsigned int var_size
; /* # bytes that variables take up. */
3414 unsigned int save_fp
; /* Nonzero if fp must be saved. */
3415 unsigned int save_lr
; /* Nonzero if lr must be saved. */
3416 unsigned int lr_slot
; /* Nonzero if the lr slot is needed. */
3417 unsigned int combine
; /* Nonzero if we can combine the allocation of
3418 variables and regs. */
3419 unsigned int interrupt
; /* Nonzero if the function is an interrupt
3421 unsigned int mask
[last_type
]; /* Masks of saved regs: gp, mdb, mdc, fp */
3424 /* Current frame information calculated by visium_compute_frame_size. */
3425 static struct visium_frame_info current_frame_info
;
3427 /* Accessor for current_frame_info.save_fp. */
3430 current_function_saves_fp (void)
3432 return current_frame_info
.save_fp
!= 0;
3435 /* Accessor for current_frame_info.save_lr. */
3438 current_function_saves_lr (void)
3440 return current_frame_info
.save_lr
!= 0;
3443 /* Accessor for current_frame_info.lr_slot. */
3446 current_function_has_lr_slot (void)
3448 return current_frame_info
.lr_slot
!= 0;
3451 /* Return non-zero if register REGNO needs to be saved in the frame. */
3454 visium_save_reg_p (int interrupt
, int regno
)
3458 case HARD_FRAME_POINTER_REGNUM
:
3459 /* This register is call-saved but handled specially. */
3463 /* This register is fixed but can be modified. */
3468 /* These registers are fixed and hold the interrupt context. */
3469 return (interrupt
!= 0);
3472 /* The other fixed registers are either immutable or special. */
3473 if (fixed_regs
[regno
])
3482 if (df_regs_ever_live_p (regno
))
3485 else if (call_used_regs
[regno
])
3488 /* To save mdb requires two temporary registers. To save mdc or
3489 any of the floating registers requires one temporary
3490 register. If this is an interrupt routine, the temporary
3491 registers need to be saved as well. These temporary registers
3492 are call used, so we only need deal with the case of leaf
3494 if (regno
== PROLOGUE_TMP_REGNUM
)
3496 if (df_regs_ever_live_p (MDB_REGNUM
)
3497 || df_regs_ever_live_p (MDC_REGNUM
))
3500 for (int i
= FP_FIRST_REGNUM
; i
<= FP_LAST_REGNUM
; i
++)
3501 if (df_regs_ever_live_p (i
))
3505 else if (regno
== PROLOGUE_TMP_REGNUM
+ 1)
3507 if (df_regs_ever_live_p (MDB_REGNUM
))
3512 return df_regs_ever_live_p (regno
) && !call_used_regs
[regno
];
3515 /* Compute the frame size required by the function. This function is called
3516 during the reload pass and also by visium_expand_prologue. */
3519 visium_compute_frame_size (int size
)
3521 const int save_area_size
= visium_reg_parm_save_area_size
;
3522 const int var_size
= VISIUM_STACK_ALIGN (size
);
3524 = frame_pointer_needed
|| df_regs_ever_live_p (HARD_FRAME_POINTER_REGNUM
);
3525 const int save_lr
= frame_pointer_needed
|| !crtl
->is_leaf
;
3526 const int lr_slot
= !save_lr
&& df_regs_ever_live_p (long_branch_regnum
);
3527 const int local_frame_offset
3528 = (save_fp
+ save_lr
+ lr_slot
) * UNITS_PER_WORD
;
3529 const int interrupt
= visium_interrupt_function_p ();
3530 unsigned int mask
[last_type
];
3539 memset (mask
, 0, last_type
* sizeof (unsigned int));
3541 /* The registers may need stacking in 2 blocks since only 32 32-bit words
3542 can be indexed from a given base address. */
3543 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
3545 if (visium_save_reg_p (interrupt
, regno
))
3547 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3548 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3549 int nbytes
= reg_type_size
[reg_type
];
3551 if (reg_size1
+ nbytes
> 32 * UNITS_PER_WORD
)
3554 reg_size1
+= nbytes
;
3556 mask
[reg_type
] |= mask_bit
;
3560 for (regno
= max_reg1
+ 1; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
3562 if (visium_save_reg_p (interrupt
, regno
))
3564 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3565 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3566 int nbytes
= reg_type_size
[reg_type
];
3568 reg_size2
+= nbytes
;
3569 mask
[reg_type
] |= mask_bit
;
3573 reg_size
= reg_size2
? reg_size2
: reg_size1
;
3574 combine
= (local_frame_offset
+ var_size
+ reg_size
) <= 32 * UNITS_PER_WORD
;
3576 = local_frame_offset
+ var_size
+ reg_size2
+ reg_size1
+ save_area_size
;
3578 current_frame_info
.save_area_size
= save_area_size
;
3579 current_frame_info
.reg_size1
= reg_size1
;
3580 current_frame_info
.max_reg1
= max_reg1
;
3581 current_frame_info
.reg_size2
= reg_size2
;
3582 current_frame_info
.var_size
= var_size
;
3583 current_frame_info
.save_fp
= save_fp
;
3584 current_frame_info
.save_lr
= save_lr
;
3585 current_frame_info
.lr_slot
= lr_slot
;
3586 current_frame_info
.combine
= combine
;
3587 current_frame_info
.interrupt
= interrupt
;
3589 memcpy (current_frame_info
.mask
, mask
, last_type
* sizeof (unsigned int));
3594 /* Helper function for INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET). Define
3595 the offset between two registers, one to be eliminated, and the other its
3596 replacement, at the start of a routine. */
3599 visium_initial_elimination_offset (int from
, int to ATTRIBUTE_UNUSED
)
3601 const int save_fp
= current_frame_info
.save_fp
;
3602 const int save_lr
= current_frame_info
.save_lr
;
3603 const int lr_slot
= current_frame_info
.lr_slot
;
3606 if (from
== FRAME_POINTER_REGNUM
)
3607 offset
= (save_fp
+ save_lr
+ lr_slot
) * UNITS_PER_WORD
;
3608 else if (from
== ARG_POINTER_REGNUM
)
3609 offset
= visium_compute_frame_size (get_frame_size ());
3616 /* For an interrupt handler, we may be saving call-clobbered registers.
3617 Say the epilogue uses these in addition to the link register. */
3620 visium_epilogue_uses (int regno
)
3622 if (regno
== LINK_REGNUM
)
3625 if (reload_completed
)
3627 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3628 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3630 return (current_frame_info
.mask
[reg_type
] & mask_bit
) != 0;
3636 /* Wrapper around emit_insn that sets RTX_FRAME_RELATED_P on the insn. */
3639 emit_frame_insn (rtx x
)
3642 RTX_FRAME_RELATED_P (x
) = 1;
3646 /* Allocate ALLOC bytes on the stack and save the registers LOW_REGNO to
3647 HIGH_REGNO at OFFSET from the stack pointer. */
3650 visium_save_regs (int alloc
, int offset
, int low_regno
, int high_regno
)
3652 /* If this is an interrupt handler function, then mark the register
3653 stores as volatile. This will prevent the instruction scheduler
3654 from scrambling the order of register saves. */
3655 const int volatile_p
= current_frame_info
.interrupt
;
3658 /* Allocate the stack space. */
3659 emit_frame_insn (gen_addsi3_flags (stack_pointer_rtx
, stack_pointer_rtx
,
3662 for (regno
= low_regno
; regno
<= high_regno
; regno
++)
3664 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3665 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3668 if (current_frame_info
.mask
[reg_type
] & mask_bit
)
3670 offset
-= reg_type_size
[reg_type
];
3676 = gen_frame_mem (SImode
,
3677 plus_constant (Pmode
,
3678 stack_pointer_rtx
, offset
));
3679 MEM_VOLATILE_P (mem
) = volatile_p
;
3680 emit_frame_insn (gen_movsi (mem
, gen_rtx_REG (SImode
, regno
)));
3686 rtx tmp
= gen_rtx_REG (DImode
, PROLOGUE_TMP_REGNUM
);
3688 = gen_frame_mem (DImode
,
3689 plus_constant (Pmode
,
3690 stack_pointer_rtx
, offset
));
3691 rtx reg
= gen_rtx_REG (DImode
, regno
);
3692 MEM_VOLATILE_P (mem
) = volatile_p
;
3693 emit_insn (gen_movdi (tmp
, reg
));
3694 /* Do not generate CFI if in interrupt handler. */
3696 emit_insn (gen_movdi (mem
, tmp
));
3699 insn
= emit_frame_insn (gen_movdi (mem
, tmp
));
3700 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3701 gen_rtx_SET (mem
, reg
));
3708 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
);
3710 = gen_frame_mem (SImode
,
3711 plus_constant (Pmode
,
3712 stack_pointer_rtx
, offset
));
3713 rtx reg
= gen_rtx_REG (SImode
, regno
);
3714 MEM_VOLATILE_P (mem
) = volatile_p
;
3715 emit_insn (gen_movsi (tmp
, reg
));
3716 insn
= emit_frame_insn (gen_movsi (mem
, tmp
));
3717 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3718 gen_rtx_SET (mem
, reg
));
3724 rtx tmp
= gen_rtx_REG (SFmode
, PROLOGUE_TMP_REGNUM
);
3726 = gen_frame_mem (SFmode
,
3727 plus_constant (Pmode
,
3728 stack_pointer_rtx
, offset
));
3729 rtx reg
= gen_rtx_REG (SFmode
, regno
);
3730 MEM_VOLATILE_P (mem
) = volatile_p
;
3731 emit_insn (gen_movsf (tmp
, reg
));
3732 insn
= emit_frame_insn (gen_movsf (mem
, tmp
));
3733 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3734 gen_rtx_SET (mem
, reg
));
3745 /* This function generates the code for function entry. */
3748 visium_expand_prologue (void)
3750 const int frame_size
= visium_compute_frame_size (get_frame_size ());
3751 const int save_area_size
= current_frame_info
.save_area_size
;
3752 const int reg_size1
= current_frame_info
.reg_size1
;
3753 const int max_reg1
= current_frame_info
.max_reg1
;
3754 const int reg_size2
= current_frame_info
.reg_size2
;
3755 const int var_size
= current_frame_info
.var_size
;
3756 const int save_fp
= current_frame_info
.save_fp
;
3757 const int save_lr
= current_frame_info
.save_lr
;
3758 const int lr_slot
= current_frame_info
.lr_slot
;
3759 const int local_frame_offset
3760 = (save_fp
+ save_lr
+ lr_slot
) * UNITS_PER_WORD
;
3761 const int combine
= current_frame_info
.combine
;
3766 /* Save the frame size for future references. */
3767 visium_frame_size
= frame_size
;
3769 if (flag_stack_usage_info
)
3770 current_function_static_stack_size
= frame_size
;
3772 /* If the registers have to be stacked in 2 blocks, stack the first one. */
3775 visium_save_regs (reg_size1
+ save_area_size
, reg_size1
, 0, max_reg1
);
3776 reg_size
= reg_size2
;
3777 first_reg
= max_reg1
+ 1;
3778 fsize
= local_frame_offset
+ var_size
+ reg_size2
;
3782 reg_size
= reg_size1
;
3784 fsize
= local_frame_offset
+ var_size
+ reg_size1
+ save_area_size
;
3787 /* If we can't combine register stacking with variable allocation, partially
3788 allocate and stack the (remaining) registers now. */
3789 if (reg_size
&& !combine
)
3790 visium_save_regs (fsize
- local_frame_offset
- var_size
, reg_size
,
3791 first_reg
, FIRST_PSEUDO_REGISTER
- 1);
3793 /* If we can combine register stacking with variable allocation, fully
3794 allocate and stack the (remaining) registers now. */
3795 if (reg_size
&& combine
)
3796 visium_save_regs (fsize
, local_frame_offset
+ var_size
+ reg_size
,
3797 first_reg
, FIRST_PSEUDO_REGISTER
- 1);
3799 /* Otherwise space may still need to be allocated for the variables. */
3802 const int alloc_size
= reg_size
? local_frame_offset
+ var_size
: fsize
;
3804 if (alloc_size
> 65535)
3806 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
), insn
;
3807 emit_insn (gen_movsi (tmp
, GEN_INT (alloc_size
)));
3808 insn
= emit_frame_insn (gen_subsi3_flags (stack_pointer_rtx
,
3811 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3812 gen_rtx_SET (stack_pointer_rtx
,
3813 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
3814 GEN_INT (-alloc_size
))));
3817 emit_frame_insn (gen_addsi3_flags (stack_pointer_rtx
,
3819 GEN_INT (-alloc_size
)));
3823 emit_frame_insn (gen_movsi (gen_frame_mem (SImode
, stack_pointer_rtx
),
3824 hard_frame_pointer_rtx
));
3826 if (frame_pointer_needed
)
3827 emit_frame_insn (gen_stack_save ());
3833 /* Normally the frame pointer and link register get saved via
3838 Indexing off sp rather than fp to store the link register
3839 avoids presenting the instruction scheduler with an initial
3840 pipeline hazard. If however the frame is needed for eg.
3841 __builtin_return_address which needs to retrieve the saved
3842 value of the link register from the stack at fp + 4 then
3843 indexing from sp can confuse the dataflow, causing the link
3844 register to be retrieved before it has been saved. */
3845 if (cfun
->machine
->frame_needed
)
3846 base_rtx
= hard_frame_pointer_rtx
;
3848 base_rtx
= stack_pointer_rtx
;
3850 mem
= gen_frame_mem (SImode
,
3851 plus_constant (Pmode
,
3852 base_rtx
, save_fp
* UNITS_PER_WORD
));
3853 emit_frame_insn (gen_movsi (mem
, gen_rtx_REG (SImode
, LINK_REGNUM
)));
3857 static GTY(()) rtx cfa_restores
;
3859 /* Queue a REG_CFA_RESTORE note until next stack manipulation insn. */
3862 visium_add_cfa_restore_note (rtx reg
)
3864 cfa_restores
= alloc_reg_note (REG_CFA_RESTORE
, reg
, cfa_restores
);
3867 /* Add queued REG_CFA_RESTORE notes to INSN, if any. */
3870 visium_add_queued_cfa_restore_notes (rtx insn
)
3875 for (last
= cfa_restores
; XEXP (last
, 1); last
= XEXP (last
, 1))
3877 XEXP (last
, 1) = REG_NOTES (insn
);
3878 REG_NOTES (insn
) = cfa_restores
;
3879 cfa_restores
= NULL_RTX
;
3882 /* Restore the registers LOW_REGNO to HIGH_REGNO from the save area at OFFSET
3883 from the stack pointer and pop DEALLOC bytes off the stack. */
3886 visium_restore_regs (int dealloc
, int offset
, int high_regno
, int low_regno
)
3888 /* If this is an interrupt handler function, then mark the register
3889 restores as volatile. This will prevent the instruction scheduler
3890 from scrambling the order of register restores. */
3891 const int volatile_p
= current_frame_info
.interrupt
;
3892 int r30_offset
= -1;
3895 for (regno
= high_regno
; regno
>= low_regno
; --regno
)
3897 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3898 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3900 if (current_frame_info
.mask
[reg_type
] & mask_bit
)
3905 /* Postpone restoring the interrupted context registers
3906 until last, since they need to be preceded by a dsi. */
3909 else if (regno
== 30)
3910 r30_offset
= offset
;
3914 = gen_frame_mem (SImode
,
3915 plus_constant (Pmode
,
3918 rtx reg
= gen_rtx_REG (SImode
, regno
);
3919 MEM_VOLATILE_P (mem
) = volatile_p
;
3920 emit_insn (gen_movsi (reg
, mem
));
3921 visium_add_cfa_restore_note (reg
);
3927 rtx tmp
= gen_rtx_REG (DImode
, PROLOGUE_TMP_REGNUM
);
3929 = gen_frame_mem (DImode
,
3930 plus_constant (Pmode
,
3931 stack_pointer_rtx
, offset
));
3932 rtx reg
= gen_rtx_REG (DImode
, regno
);
3933 MEM_VOLATILE_P (mem
) = volatile_p
;
3934 emit_insn (gen_movdi (tmp
, mem
));
3935 emit_insn (gen_movdi (reg
, tmp
));
3936 /* Do not generate CFI if in interrupt handler. */
3938 visium_add_cfa_restore_note (reg
);
3944 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
);
3946 = gen_frame_mem (SImode
,
3947 plus_constant (Pmode
,
3948 stack_pointer_rtx
, offset
));
3949 rtx reg
= gen_rtx_REG (SImode
, regno
);
3950 MEM_VOLATILE_P (mem
) = volatile_p
;
3951 emit_insn (gen_movsi (tmp
, mem
));
3952 emit_insn (gen_movsi (reg
, tmp
));
3953 visium_add_cfa_restore_note (reg
);
3959 rtx tmp
= gen_rtx_REG (SFmode
, PROLOGUE_TMP_REGNUM
);
3961 = gen_frame_mem (SFmode
,
3962 plus_constant (Pmode
,
3963 stack_pointer_rtx
, offset
));
3964 rtx reg
= gen_rtx_REG (SFmode
, regno
);
3965 MEM_VOLATILE_P (mem
) = volatile_p
;
3966 emit_insn (gen_movsf (tmp
, mem
));
3967 emit_insn (gen_movsf (reg
, tmp
));
3968 visium_add_cfa_restore_note (reg
);
3976 offset
+= reg_type_size
[reg_type
];
3980 /* If the interrupted context needs to be restored, precede the
3981 restores of r29 and r30 by a dsi. */
3982 if (r30_offset
>= 0)
3984 emit_insn (gen_dsi ());
3985 emit_move_insn (gen_rtx_REG (SImode
, 30),
3986 gen_frame_mem (SImode
,
3987 plus_constant (Pmode
,
3990 emit_move_insn (gen_rtx_REG (SImode
, 29),
3991 gen_frame_mem (SImode
,
3992 plus_constant (Pmode
,
3997 /* Deallocate the stack space. */
3998 rtx insn
= emit_frame_insn (gen_stack_pop (GEN_INT (dealloc
)));
3999 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
4000 gen_rtx_SET (stack_pointer_rtx
,
4001 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
4002 GEN_INT (dealloc
))));
4003 visium_add_queued_cfa_restore_notes (insn
);
4006 /* This function generates the code for function exit. */
4009 visium_expand_epilogue (void)
4011 const int save_area_size
= current_frame_info
.save_area_size
;
4012 const int reg_size1
= current_frame_info
.reg_size1
;
4013 const int max_reg1
= current_frame_info
.max_reg1
;
4014 const int reg_size2
= current_frame_info
.reg_size2
;
4015 const int var_size
= current_frame_info
.var_size
;
4016 const int restore_fp
= current_frame_info
.save_fp
;
4017 const int restore_lr
= current_frame_info
.save_lr
;
4018 const int lr_slot
= current_frame_info
.lr_slot
;
4019 const int local_frame_offset
4020 = (restore_fp
+ restore_lr
+ lr_slot
) * UNITS_PER_WORD
;
4021 const int combine
= current_frame_info
.combine
;
4026 /* Do not bother restoring the stack pointer if it hasn't been changed in
4027 the function since it was saved _after_ the allocation of the frame. */
4028 if (!crtl
->sp_is_unchanging
)
4029 emit_insn (gen_stack_restore ());
4031 /* Restore the frame pointer if necessary. The usual code would be:
4036 but for the MCM this constitutes a stall/hazard so it is changed to:
4041 if the stack pointer has actually been restored. */
4046 if (TARGET_MCM
&& !crtl
->sp_is_unchanging
)
4047 src
= gen_frame_mem (SImode
, hard_frame_pointer_rtx
);
4049 src
= gen_frame_mem (SImode
, stack_pointer_rtx
);
4051 rtx insn
= emit_frame_insn (gen_movsi (hard_frame_pointer_rtx
, src
));
4052 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
4053 gen_rtx_SET (stack_pointer_rtx
,
4054 hard_frame_pointer_rtx
));
4055 visium_add_cfa_restore_note (hard_frame_pointer_rtx
);
4058 /* Restore the link register if necessary. */
4061 rtx mem
= gen_frame_mem (SImode
,
4062 plus_constant (Pmode
,
4064 restore_fp
* UNITS_PER_WORD
));
4065 rtx reg
= gen_rtx_REG (SImode
, LINK_REGNUM
);
4066 emit_insn (gen_movsi (reg
, mem
));
4067 visium_add_cfa_restore_note (reg
);
4070 /* If we have two blocks of registers, deal with the second one first. */
4073 reg_size
= reg_size2
;
4074 last_reg
= max_reg1
+ 1;
4075 fsize
= local_frame_offset
+ var_size
+ reg_size2
;
4079 reg_size
= reg_size1
;
4081 fsize
= local_frame_offset
+ var_size
+ reg_size1
+ save_area_size
;
4084 /* If the variable allocation could be combined with register stacking,
4085 restore the (remaining) registers and fully deallocate now. */
4086 if (reg_size
&& combine
)
4087 visium_restore_regs (fsize
, local_frame_offset
+ var_size
,
4088 FIRST_PSEUDO_REGISTER
- 1, last_reg
);
4090 /* Otherwise deallocate the variables first. */
4093 const int pop_size
= reg_size
? local_frame_offset
+ var_size
: fsize
;
4096 if (pop_size
> 65535)
4098 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
);
4099 emit_move_insn (tmp
, GEN_INT (pop_size
));
4100 insn
= emit_frame_insn (gen_stack_pop (tmp
));
4103 insn
= emit_frame_insn (gen_stack_pop (GEN_INT (pop_size
)));
4104 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
4105 gen_rtx_SET (stack_pointer_rtx
,
4106 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
4107 GEN_INT (pop_size
))));
4108 visium_add_queued_cfa_restore_notes (insn
);
4111 /* If the variable allocation couldn't be combined with register stacking,
4112 restore the (remaining) registers now and partially deallocate. */
4113 if (reg_size
&& !combine
)
4114 visium_restore_regs (fsize
- local_frame_offset
- var_size
, 0,
4115 FIRST_PSEUDO_REGISTER
- 1, last_reg
);
4117 /* If the first block of registers has yet to be restored, do it now. */
4119 visium_restore_regs (reg_size1
+ save_area_size
, 0, max_reg1
, 0);
4121 /* If this is an exception return, make the necessary stack adjustment. */
4122 if (crtl
->calls_eh_return
)
4123 emit_insn (gen_stack_pop (EH_RETURN_STACKADJ_RTX
));
4126 /* Return true if it is appropriate to emit `return' instructions in the
4127 body of a function. */
4130 visium_can_use_return_insn_p (void)
4132 return reload_completed
4133 && visium_frame_size
== 0
4134 && !visium_interrupt_function_p ();
4137 /* Return the register class required for an intermediate register used to
4138 copy a register of RCLASS from/to X. If no such intermediate register is
4139 required, return NO_REGS. If more than one such intermediate register is
4140 required, describe the one that is closest in the copy chain to the reload
4144 visium_secondary_reload (bool in_p ATTRIBUTE_UNUSED
, rtx x
,
4146 enum machine_mode mode ATTRIBUTE_UNUSED
,
4147 secondary_reload_info
*sri ATTRIBUTE_UNUSED
)
4149 int regno
= true_regnum (x
);
4151 /* For MDB, MDC and FP_REGS, a general register is needed for a move to
4153 if (regno
== -1 && (rclass
== MDB
|| rclass
== MDC
|| rclass
== FP_REGS
))
4154 return GENERAL_REGS
;
4156 /* Moves between MDB, MDC and FP_REGS also require a general register. */
4157 else if (((regno
== R_MDB
|| regno
== R_MDC
) && rclass
== FP_REGS
)
4158 || (FP_REGISTER_P (regno
) && (rclass
== MDB
|| rclass
== MDC
)))
4159 return GENERAL_REGS
;
4161 /* Finally an (unlikely ?) move between MDB and MDC needs a general reg. */
4162 else if ((regno
== R_MDB
&& rclass
== MDC
)
4163 || (rclass
== MDB
&& regno
== R_MDC
))
4164 return GENERAL_REGS
;
4169 /* Return true if pseudos that have been assigned to registers of RCLASS
4170 would likely be spilled because registers of RCLASS are needed for
4174 visium_class_likely_spilled_p (reg_class_t rclass ATTRIBUTE_UNUSED
)
4176 /* Return false for classes R1, R2 and R3, which are intended to be used
4177 only in the source code in conjunction with block move instructions. */
4181 /* Return the register number if OP is a REG or a SUBREG of a REG, and
4182 INVALID_REGNUM in all the other cases. */
4185 reg_or_subreg_regno (rtx op
)
4189 if (GET_CODE (op
) == REG
)
4191 else if (GET_CODE (op
) == SUBREG
&& GET_CODE (SUBREG_REG (op
)) == REG
)
4193 if (REGNO (SUBREG_REG (op
)) < FIRST_PSEUDO_REGISTER
)
4194 regno
= subreg_regno (op
);
4196 regno
= REGNO (SUBREG_REG (op
));
4199 regno
= INVALID_REGNUM
;
4204 #include "gt-visium.h"