1 /* Output routines for Visium.
2 Copyright (C) 2002-2015 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"
29 #include "tree-core.h"
30 #include "fold-const.h"
31 #include "tree-check.h"
33 #include "stringpool.h"
34 #include "stor-layout.h"
39 #include "hard-reg-set.h"
40 #include "insn-config.h"
41 #include "conditions.h"
43 #include "insn-attr.h"
52 #include "diagnostic-core.h"
56 #include "target-def.h"
57 #include "common/common-target.h"
59 #include "basic-block.h"
60 #include "gimple-expr.h"
62 #include "langhooks.h"
64 #include "tm-constrs.h"
68 #include "tree-pass.h"
72 /* Machine specific function data. */
73 struct GTY (()) machine_function
75 /* Size of the frame of the function. */
78 /* Size of the reg parm save area, non-zero only for functions with variable
79 argument list. We cannot use the crtl->args.pretend_args_size machinery
80 for this purpose because this size is added to virtual_incoming_args_rtx
81 to give the location of the first parameter passed by the caller on the
82 stack and virtual_incoming_args_rtx is also the location of the first
83 parameter on the stack. So crtl->args.pretend_args_size can be non-zero
84 only if the first non-register named parameter is not passed entirely on
85 the stack and this runs afoul of the need to have a reg parm save area
86 even with a variable argument list starting on the stack because of the
87 separate handling of general and floating-point registers. */
88 int reg_parm_save_area_size
;
90 /* True if we have created an rtx which relies on the frame pointer. */
93 /* True if we have exposed the flags register. From this moment on, we
94 cannot generate simple operations for integer registers. We could
95 use reload_completed for this purpose, but this would cripple the
96 postreload CSE and GCSE passes which run before postreload split. */
100 #define visium_frame_size cfun->machine->frame_size
101 #define visium_reg_parm_save_area_size cfun->machine->reg_parm_save_area_size
102 #define visium_frame_needed cfun->machine->frame_needed
103 #define visium_flags_exposed cfun->machine->flags_exposed
105 /* 1 if the next opcode is to be specially indented. */
106 int visium_indent_opcode
= 0;
108 /* Register number used for long branches when LR isn't available. It
109 must be a call-used register since it isn't saved on function entry.
110 We do not care whether the branch is predicted or not on the GR6,
111 given how unlikely it is to have a long branch in a leaf function. */
112 static unsigned int long_branch_regnum
= 31;
114 static void visium_output_address (FILE *, enum machine_mode
, rtx
);
115 static tree
visium_handle_interrupt_attr (tree
*, tree
, tree
, int, bool *);
116 static inline bool current_function_saves_fp (void);
117 static inline bool current_function_saves_lr (void);
118 static inline bool current_function_has_lr_slot (void);
120 /* Supported attributes:
121 interrupt -- specifies this function is an interrupt handler. */
122 static const struct attribute_spec visium_attribute_table
[] =
124 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
125 affects_type_identity } */
126 {"interrupt", 0, 0, true, false, false, visium_handle_interrupt_attr
, false},
127 {NULL
, 0, 0, false, false, false, NULL
, false}
130 static struct machine_function
*visium_init_machine_status (void);
132 /* Target hooks and TARGET_INITIALIZER */
134 static bool visium_pass_by_reference (cumulative_args_t
, enum machine_mode
,
137 static rtx
visium_function_arg (cumulative_args_t
, enum machine_mode
,
140 static void visium_function_arg_advance (cumulative_args_t
, enum machine_mode
,
143 static bool visium_return_in_memory (const_tree
, const_tree fntype
);
145 static rtx
visium_function_value (const_tree
, const_tree fn_decl_or_type
,
148 static rtx
visium_libcall_value (enum machine_mode
, const_rtx
);
150 static void visium_setup_incoming_varargs (cumulative_args_t
,
154 static void visium_va_start (tree valist
, rtx nextarg
);
156 static tree
visium_gimplify_va_arg (tree
, tree
, gimple_seq
*, gimple_seq
*);
158 static bool visium_function_ok_for_sibcall (tree
, tree
);
160 static bool visium_frame_pointer_required (void);
162 static tree
visium_build_builtin_va_list (void);
164 static rtx_insn
*visium_md_asm_adjust (vec
<rtx
> &, vec
<rtx
> &,
166 vec
<rtx
> &, HARD_REG_SET
&);
168 static bool visium_legitimate_constant_p (enum machine_mode
, rtx
);
170 static bool visium_legitimate_address_p (enum machine_mode
, rtx
, bool);
172 static void visium_conditional_register_usage (void);
174 static rtx
visium_legitimize_address (rtx
, rtx
, enum machine_mode
);
176 static reg_class_t
visium_secondary_reload (bool, rtx
, reg_class_t
,
178 secondary_reload_info
*);
180 static bool visium_class_likely_spilled_p (reg_class_t
);
182 static void visium_trampoline_init (rtx
, tree
, rtx
);
184 static int visium_issue_rate (void);
186 static int visium_adjust_priority (rtx_insn
*, int);
188 static int visium_adjust_cost (rtx_insn
*, rtx
, rtx_insn
*, int);
190 static int visium_register_move_cost (enum machine_mode
, reg_class_t
,
193 static int visium_memory_move_cost (enum machine_mode
, reg_class_t
, bool);
195 static bool visium_rtx_costs (rtx
, int, int, int, int *, bool);
197 static void visium_option_override (void);
199 static unsigned int visium_reorg (void);
201 /* Setup the global target hooks structure. */
203 #undef TARGET_MAX_ANCHOR_OFFSET
204 #define TARGET_MAX_ANCHOR_OFFSET 31
206 #undef TARGET_PASS_BY_REFERENCE
207 #define TARGET_PASS_BY_REFERENCE visium_pass_by_reference
209 #undef TARGET_FUNCTION_ARG
210 #define TARGET_FUNCTION_ARG visium_function_arg
212 #undef TARGET_FUNCTION_ARG_ADVANCE
213 #define TARGET_FUNCTION_ARG_ADVANCE visium_function_arg_advance
215 #undef TARGET_RETURN_IN_MEMORY
216 #define TARGET_RETURN_IN_MEMORY visium_return_in_memory
218 #undef TARGET_FUNCTION_VALUE
219 #define TARGET_FUNCTION_VALUE visium_function_value
221 #undef TARGET_LIBCALL_VALUE
222 #define TARGET_LIBCALL_VALUE visium_libcall_value
224 #undef TARGET_SETUP_INCOMING_VARARGS
225 #define TARGET_SETUP_INCOMING_VARARGS visium_setup_incoming_varargs
227 #undef TARGET_EXPAND_BUILTIN_VA_START
228 #define TARGET_EXPAND_BUILTIN_VA_START visium_va_start
230 #undef TARGET_BUILD_BUILTIN_VA_LIST
231 #define TARGET_BUILD_BUILTIN_VA_LIST visium_build_builtin_va_list
233 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
234 #define TARGET_GIMPLIFY_VA_ARG_EXPR visium_gimplify_va_arg
236 #undef TARGET_LEGITIMATE_CONSTANT_P
237 #define TARGET_LEGITIMATE_CONSTANT_P visium_legitimate_constant_p
239 #undef TARGET_LEGITIMATE_ADDRESS_P
240 #define TARGET_LEGITIMATE_ADDRESS_P visium_legitimate_address_p
242 #undef TARGET_ATTRIBUTE_TABLE
243 #define TARGET_ATTRIBUTE_TABLE visium_attribute_table
245 #undef TARGET_ADDRESS_COST
246 #define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
248 #undef TARGET_STRICT_ARGUMENT_NAMING
249 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
251 #undef TARGET_SCHED_ISSUE_RATE
252 #define TARGET_SCHED_ISSUE_RATE visium_issue_rate
254 #undef TARGET_SCHED_ADJUST_PRIORITY
255 #define TARGET_SCHED_ADJUST_PRIORITY visium_adjust_priority
257 #undef TARGET_SCHED_ADJUST_COST
258 #define TARGET_SCHED_ADJUST_COST visium_adjust_cost
260 #undef TARGET_MEMORY_MOVE_COST
261 #define TARGET_MEMORY_MOVE_COST visium_memory_move_cost
263 #undef TARGET_REGISTER_MOVE_COST
264 #define TARGET_REGISTER_MOVE_COST visium_register_move_cost
266 #undef TARGET_RTX_COSTS
267 #define TARGET_RTX_COSTS visium_rtx_costs
269 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
270 #define TARGET_FUNCTION_OK_FOR_SIBCALL visium_function_ok_for_sibcall
272 #undef TARGET_FRAME_POINTER_REQUIRED
273 #define TARGET_FRAME_POINTER_REQUIRED visium_frame_pointer_required
275 #undef TARGET_SECONDARY_RELOAD
276 #define TARGET_SECONDARY_RELOAD visium_secondary_reload
278 #undef TARGET_CLASS_LIKELY_SPILLED_P
279 #define TARGET_CLASS_LIKELY_SPILLED_P visium_class_likely_spilled_p
281 #undef TARGET_LEGITIMIZE_ADDRESS
282 #define TARGET_LEGITIMIZE_ADDRESS visium_legitimize_address
284 #undef TARGET_OPTION_OVERRIDE
285 #define TARGET_OPTION_OVERRIDE visium_option_override
287 #undef TARGET_CONDITIONAL_REGISTER_USAGE
288 #define TARGET_CONDITIONAL_REGISTER_USAGE visium_conditional_register_usage
290 #undef TARGET_TRAMPOLINE_INIT
291 #define TARGET_TRAMPOLINE_INIT visium_trampoline_init
293 #undef TARGET_MD_ASM_ADJUST
294 #define TARGET_MD_ASM_ADJUST visium_md_asm_adjust
296 #undef TARGET_FLAGS_REGNUM
297 #define TARGET_FLAGS_REGNUM FLAGS_REGNUM
299 struct gcc_target targetm
= TARGET_INITIALIZER
;
303 const pass_data pass_data_visium_reorg
=
307 OPTGROUP_NONE
, /* optinfo_flags */
308 TV_MACH_DEP
, /* tv_id */
309 0, /* properties_required */
310 0, /* properties_provided */
311 0, /* properties_destroyed */
312 0, /* todo_flags_start */
313 0, /* todo_flags_finish */
316 class pass_visium_reorg
: public rtl_opt_pass
319 pass_visium_reorg(gcc::context
*ctxt
)
320 : rtl_opt_pass(pass_data_visium_reorg
, ctxt
)
323 /* opt_pass methods: */
324 virtual unsigned int execute (function
*)
326 return visium_reorg ();
329 }; // class pass_work_around_errata
334 make_pass_visium_reorg (gcc::context
*ctxt
)
336 return new pass_visium_reorg (ctxt
);
339 /* Options override for Visium. */
342 visium_option_override (void)
345 warning (OPT_fpic
, "-fpic is not supported");
347 warning (OPT_fPIC
, "-fPIC is not supported");
349 /* MCM is the default in the GR5/GR6 era. */
350 target_flags
|= MASK_MCM
;
352 /* FPU is the default with MCM, but don't override an explicit option. */
353 if ((target_flags_explicit
& MASK_FPU
) == 0)
354 target_flags
|= MASK_FPU
;
356 /* The supervisor mode is the default. */
357 if ((target_flags_explicit
& MASK_SV_MODE
) == 0)
358 target_flags
|= MASK_SV_MODE
;
360 /* The GR6 has the Block Move Instructions and an IEEE-compliant FPU. */
361 if (visium_cpu_and_features
== PROCESSOR_GR6
)
363 target_flags
|= MASK_BMI
;
364 if (target_flags
& MASK_FPU
)
365 target_flags
|= MASK_FPU_IEEE
;
368 /* Set -mtune from -mcpu if not specified. */
369 if (!global_options_set
.x_visium_cpu
)
370 visium_cpu
= visium_cpu_and_features
;
372 /* Align functions on 256-byte (32-quadword) for GR5 and 64-byte (8-quadword)
373 boundaries for GR6 so they start a new burst mode window. */
374 if (align_functions
== 0)
376 if (visium_cpu
== PROCESSOR_GR6
)
377 align_functions
= 64;
379 align_functions
= 256;
381 /* Allow the size of compilation units to double because of inlining.
382 In practice the global size of the object code is hardly affected
383 because the additional instructions will take up the padding. */
384 maybe_set_param_value (PARAM_INLINE_UNIT_GROWTH
, 100,
385 global_options
.x_param_values
,
386 global_options_set
.x_param_values
);
389 /* Likewise for loops. */
390 if (align_loops
== 0)
392 if (visium_cpu
== PROCESSOR_GR6
)
397 /* But not if they are too far away from a 256-byte boundary. */
398 align_loops_max_skip
= 31;
402 /* Align all jumps on quadword boundaries for the burst mode, and even
403 on 8-quadword boundaries for GR6 so they start a new window. */
404 if (align_jumps
== 0)
406 if (visium_cpu
== PROCESSOR_GR6
)
412 /* We register a machine-specific pass. This pass must be scheduled as
413 late as possible so that we have the (essentially) final form of the
414 insn stream to work on. Registering the pass must be done at start up.
415 It's convenient to do it here. */
416 opt_pass
*visium_reorg_pass
= make_pass_visium_reorg (g
);
417 struct register_pass_info insert_pass_visium_reorg
=
419 visium_reorg_pass
, /* pass */
420 "dbr", /* reference_pass_name */
421 1, /* ref_pass_instance_number */
422 PASS_POS_INSERT_AFTER
/* po_op */
424 register_pass (&insert_pass_visium_reorg
);
427 /* Return the number of instructions that can issue on the same cycle. */
430 visium_issue_rate (void)
445 /* Return the adjusted PRIORITY of INSN. */
448 visium_adjust_priority (rtx_insn
*insn
, int priority
)
450 /* On the GR5, we slightly increase the priority of writes in order to avoid
451 scheduling a read on the next cycle. This is necessary in addition to the
452 associated insn reservation because there are no data dependencies.
453 We also slightly increase the priority of reads from ROM in order to group
454 them as much as possible. These reads are a bit problematic because they
455 conflict with the instruction fetches, i.e. the data and instruction buses
456 tread on each other's toes when they are executed. */
457 if (visium_cpu
== PROCESSOR_GR5
460 && recog_memoized (insn
) >= 0)
462 enum attr_type attr_type
= get_attr_type (insn
);
463 if (attr_type
== TYPE_REG_MEM
464 || (attr_type
== TYPE_MEM_REG
465 && MEM_READONLY_P (SET_SRC (PATTERN (insn
)))))
472 /* Adjust the cost of a scheduling dependency. Return the new cost of
473 a dependency LINK of INSN on DEP_INSN. COST is the current cost. */
476 visium_adjust_cost (rtx_insn
*insn
, rtx link
, rtx_insn
*dep_insn
, int cost
)
478 enum attr_type attr_type
;
480 /* Don't adjust costs for true dependencies as they are described with
481 bypasses. But we make an exception for the first scheduling pass to
482 help the subsequent postreload compare elimination pass. */
483 if (REG_NOTE_KIND (link
) == REG_DEP_TRUE
)
485 if (!reload_completed
486 && recog_memoized (insn
) >= 0
487 && get_attr_type (insn
) == TYPE_CMP
)
489 rtx pat
= PATTERN (insn
);
490 gcc_assert (GET_CODE (pat
) == SET
);
491 rtx src
= SET_SRC (pat
);
493 /* Only the branches can be modified by the postreload compare
494 elimination pass, not the cstores because they accept only
495 unsigned comparison operators and they are eliminated if
496 one of the operands is zero. */
497 if (GET_CODE (src
) == IF_THEN_ELSE
498 && XEXP (XEXP (src
, 0), 1) == const0_rtx
499 && recog_memoized (dep_insn
) >= 0)
501 enum attr_type dep_attr_type
= get_attr_type (dep_insn
);
503 /* The logical instructions use CCmode and thus work with any
504 comparison operator, whereas the arithmetic instructions use
505 CC_NOOVmode and thus work with only a small subset. */
506 if (dep_attr_type
== TYPE_LOGIC
507 || (dep_attr_type
== TYPE_ARITH
508 && visium_noov_operator (XEXP (src
, 0),
509 GET_MODE (XEXP (src
, 0)))))
517 if (recog_memoized (insn
) < 0)
520 attr_type
= get_attr_type (insn
);
522 /* Anti dependency: DEP_INSN reads a register that INSN writes some
524 if (REG_NOTE_KIND (link
) == REG_DEP_ANTI
)
526 /* On the GR5, the latency of FP instructions needs to be taken into
527 account for every dependency involving a write. */
528 if (attr_type
== TYPE_REG_FP
&& visium_cpu
== PROCESSOR_GR5
)
531 rtx pat
= PATTERN (insn
);
532 rtx dep_pat
= PATTERN (dep_insn
);
534 if (GET_CODE (pat
) != SET
|| GET_CODE (dep_pat
) != SET
)
535 /* If this happens, we have to extend this to schedule
536 optimally. Return 0 for now. */
539 if (reg_mentioned_p (SET_DEST (pat
), SET_SRC (dep_pat
)))
541 if (recog_memoized (dep_insn
) < 0)
544 switch (get_attr_type (dep_insn
))
552 /* A fload can't be issued until a preceding arithmetic
553 operation has finished if the target of the fload is
554 any of the sources (or destination) of the arithmetic
555 operation. Note that the latency may be (much)
556 greater than this if the preceding instruction
557 concerned is in a queue. */
558 return insn_default_latency (dep_insn
);
566 /* On the GR6, we try to make sure that the link register is restored
567 sufficiently ahead of the return as to yield a correct prediction
568 from the branch predictor. By default there is no true dependency
569 but an anti dependency between them, so we simply reuse it. */
570 else if (attr_type
== TYPE_RET
&& visium_cpu
== PROCESSOR_GR6
)
572 rtx dep_pat
= PATTERN (dep_insn
);
573 if (GET_CODE (dep_pat
) == SET
574 && REG_P (SET_DEST (dep_pat
))
575 && REGNO (SET_DEST (dep_pat
)) == LINK_REGNUM
)
579 /* For other anti dependencies, the cost is 0. */
583 /* Output dependency: DEP_INSN writes a register that INSN writes some
585 else if (REG_NOTE_KIND (link
) == REG_DEP_OUTPUT
)
587 /* On the GR5, the latency of FP instructions needs to be taken into
588 account for every dependency involving a write. */
589 if (attr_type
== TYPE_REG_FP
&& visium_cpu
== PROCESSOR_GR5
)
592 rtx pat
= PATTERN (insn
);
593 rtx dep_pat
= PATTERN (dep_insn
);
595 if (GET_CODE (pat
) != SET
|| GET_CODE (dep_pat
) != SET
)
596 /* If this happens, we have to extend this to schedule
597 optimally. Return 0 for now. */
600 if (reg_mentioned_p (SET_DEST (pat
), SET_DEST (dep_pat
)))
602 if (recog_memoized (dep_insn
) < 0)
605 switch (get_attr_type (dep_insn
))
613 /* A fload can't be issued until a preceding arithmetic
614 operation has finished if the target of the fload is
615 the destination of the arithmetic operation. Note that
616 the latency may be (much) greater than this if the
617 preceding instruction concerned is in a queue. */
618 return insn_default_latency (dep_insn
);
626 /* For other output dependencies, the cost is 0. */
633 /* Handle an "interrupt_handler" attribute; arguments as in
634 struct attribute_spec.handler. */
637 visium_handle_interrupt_attr (tree
*node
, tree name
,
638 tree args ATTRIBUTE_UNUSED
,
639 int flags ATTRIBUTE_UNUSED
,
642 if (TREE_CODE (*node
) != FUNCTION_DECL
)
644 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
646 *no_add_attrs
= true;
648 else if (!TARGET_SV_MODE
)
650 error ("an interrupt handler cannot be compiled with -muser-mode");
651 *no_add_attrs
= true;
657 /* Return non-zero if the current function is an interrupt function. */
660 visium_interrupt_function_p (void)
663 lookup_attribute ("interrupt",
664 DECL_ATTRIBUTES (current_function_decl
)) != NULL_TREE
;
667 /* Conditionally modify the settings of the register file. */
670 visium_conditional_register_usage (void)
672 /* If the supervisor mode is disabled, mask some general registers. */
675 if (visium_cpu_and_features
== PROCESSOR_GR5
)
677 fixed_regs
[24] = call_used_regs
[24] = 1;
678 fixed_regs
[25] = call_used_regs
[25] = 1;
679 fixed_regs
[26] = call_used_regs
[26] = 1;
680 fixed_regs
[27] = call_used_regs
[27] = 1;
681 fixed_regs
[28] = call_used_regs
[28] = 1;
682 call_really_used_regs
[24] = 0;
683 call_really_used_regs
[25] = 0;
684 call_really_used_regs
[26] = 0;
685 call_really_used_regs
[27] = 0;
686 call_really_used_regs
[28] = 0;
689 fixed_regs
[31] = call_used_regs
[31] = 1;
690 call_really_used_regs
[31] = 0;
692 /* We also need to change the long-branch register. */
693 if (visium_cpu_and_features
== PROCESSOR_GR5
)
694 long_branch_regnum
= 20;
696 long_branch_regnum
= 28;
699 /* If the FPU is disabled, mask the FP registers. */
702 for (int i
= FP_FIRST_REGNUM
; i
<= FP_LAST_REGNUM
; i
++)
704 fixed_regs
[i
] = call_used_regs
[i
] = 1;
705 call_really_used_regs
[i
] = 0;
710 /* Prepend to CLOBBERS hard registers that are automatically clobbered for
711 an asm We do this for the FLAGS to maintain source compatibility with
712 the original cc0-based compiler. */
715 visium_md_asm_adjust (vec
<rtx
> &/*outputs*/, vec
<rtx
> &/*inputs*/,
716 vec
<const char *> &/*constraints*/,
717 vec
<rtx
> &clobbers
, HARD_REG_SET
&clobbered_regs
)
719 clobbers
.safe_push (gen_rtx_REG (CCmode
, FLAGS_REGNUM
));
720 SET_HARD_REG_BIT (clobbered_regs
, FLAGS_REGNUM
);
724 /* Return true if X is a legitimate constant for a MODE immediate operand.
725 X is guaranteed to satisfy the CONSTANT_P predicate. */
728 visium_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED
,
729 rtx x ATTRIBUTE_UNUSED
)
734 /* Compute the alignment for a variable. The alignment of an aggregate is
735 set to be at least that of a scalar less than or equal to it in size. */
738 visium_data_alignment (tree type
, unsigned int align
)
740 if (AGGREGATE_TYPE_P (type
)
742 && TREE_CODE (TYPE_SIZE (type
)) == INTEGER_CST
&& align
< 32)
744 if (TREE_INT_CST_LOW (TYPE_SIZE (type
)) >= 32)
747 if (TREE_INT_CST_LOW (TYPE_SIZE (type
)) >= 16 && align
< 16)
754 /* Helper function for HARD_REGNO_RENAME_OK (FROM, TO). Return non-zero if
755 it is OK to rename a hard register FROM to another hard register TO. */
758 visium_hard_regno_rename_ok (unsigned int from ATTRIBUTE_UNUSED
,
761 /* If the function doesn't save LR, then the long-branch register will be
762 used for long branches so we need to know whether it is live before the
763 frame layout is computed. */
764 if (!current_function_saves_lr () && to
== long_branch_regnum
)
767 /* Interrupt functions can only use registers that have already been
768 saved by the prologue, even if they would normally be call-clobbered. */
770 && !df_regs_ever_live_p (to
)
771 && visium_interrupt_function_p ())
777 /* Return true if it is ok to do sibling call optimization for the specified
778 call expression EXP. DECL will be the called function, or NULL if this
779 is an indirect call. */
782 visium_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED
,
783 tree exp ATTRIBUTE_UNUSED
)
785 return !visium_interrupt_function_p ();
788 /* Prepare operands for a move define_expand in MODE. */
791 prepare_move_operands (rtx
*operands
, enum machine_mode mode
)
793 /* If the output is not a register, the input must be. */
794 if (GET_CODE (operands
[0]) == MEM
&& !reg_or_0_operand (operands
[1], mode
))
795 operands
[1] = force_reg (mode
, operands
[1]);
798 /* Return true if the operands are valid for a simple move insn. */
801 ok_for_simple_move_operands (rtx
*operands
, enum machine_mode mode
)
803 /* One of the operands must be a register. */
804 if (!register_operand (operands
[0], mode
)
805 && !reg_or_0_operand (operands
[1], mode
))
808 /* Once the flags are exposed, no simple moves between integer registers. */
809 if (visium_flags_exposed
810 && gpc_reg_operand (operands
[0], mode
)
811 && gpc_reg_operand (operands
[1], mode
))
817 /* Return true if the operands are valid for a simple move strict insn. */
820 ok_for_simple_move_strict_operands (rtx
*operands
, enum machine_mode mode
)
822 /* Once the flags are exposed, no simple moves between integer registers.
823 Note that, in QImode only, a zero source counts as an integer register
824 since it will be emitted as r0. */
825 if (visium_flags_exposed
826 && gpc_reg_operand (operands
[0], mode
)
827 && (gpc_reg_operand (operands
[1], mode
)
828 || (mode
== QImode
&& operands
[1] == const0_rtx
)))
834 /* Return true if the operands are valid for a simple arithmetic or logical
838 ok_for_simple_arith_logic_operands (rtx
*, enum machine_mode
)
840 /* Once the flags are exposed, no simple arithmetic or logical operations
841 between integer registers. */
842 return !visium_flags_exposed
;
845 /* Return non-zero if a branch or call instruction will be emitting a nop
846 into its delay slot. */
849 empty_delay_slot (rtx_insn
*insn
)
853 /* If no previous instruction (should not happen), return true. */
854 if (PREV_INSN (insn
) == NULL
)
857 seq
= NEXT_INSN (PREV_INSN (insn
));
858 if (GET_CODE (PATTERN (seq
)) == SEQUENCE
)
864 /* Wrapper around single_set which returns the first SET of a pair if the
865 second SET is to the flags register. */
868 single_set_and_flags (rtx_insn
*insn
)
870 if (multiple_sets (insn
))
872 rtx pat
= PATTERN (insn
);
873 if (XVECLEN (pat
, 0) == 2
874 && GET_CODE (XVECEXP (pat
, 0, 1)) == SET
875 && REG_P (SET_DEST (XVECEXP (pat
, 0, 1)))
876 && REGNO (SET_DEST (XVECEXP (pat
, 0, 1))) == FLAGS_REGNUM
)
877 return XVECEXP (pat
, 0, 0);
880 return single_set (insn
);
883 /* This is called with OUT_INSN an instruction setting a (base) register
884 and IN_INSN a read or a write. Return 1 if these instructions together
885 constitute a pipeline hazard.
887 On the original architecture, a pipeline data hazard occurs when the Dest
888 of one instruction becomes the SrcA for an immediately following READ or
889 WRITE instruction with a non-zero index (indexing occurs at the decode
890 stage and so a NOP must be inserted in-between for this to work).
897 On the MCM, the non-zero index condition is lifted but the hazard is
898 patched up by the hardware through the injection of wait states:
903 We nevertheless try to schedule instructions around this. */
906 gr5_hazard_bypass_p (rtx_insn
*out_insn
, rtx_insn
*in_insn
)
908 rtx out_set
, in_set
, dest
, memexpr
;
909 unsigned int out_reg
, in_reg
;
911 /* A CALL is storage register class, but the link register is of no
913 if (GET_CODE (out_insn
) == CALL_INSN
)
916 out_set
= single_set_and_flags (out_insn
);
917 dest
= SET_DEST (out_set
);
919 /* Should be no stall/hazard if OUT_INSN is MEM := ???. This only
920 occurs prior to reload. */
921 if (GET_CODE (dest
) == MEM
)
924 if (GET_CODE (dest
) == STRICT_LOW_PART
)
925 dest
= XEXP (dest
, 0);
926 if (GET_CODE (dest
) == SUBREG
)
927 dest
= SUBREG_REG (dest
);
928 out_reg
= REGNO (dest
);
930 in_set
= single_set_and_flags (in_insn
);
932 /* If IN_INSN is MEM := MEM, it's the source that counts. */
933 if (GET_CODE (SET_SRC (in_set
)) == MEM
)
934 memexpr
= XEXP (SET_SRC (in_set
), 0);
936 memexpr
= XEXP (SET_DEST (in_set
), 0);
938 if (GET_CODE (memexpr
) == PLUS
)
940 memexpr
= XEXP (memexpr
, 0);
941 if (GET_CODE (memexpr
) == SUBREG
)
942 in_reg
= REGNO (SUBREG_REG (memexpr
));
944 in_reg
= REGNO (memexpr
);
946 if (in_reg
== out_reg
)
951 if (GET_CODE (memexpr
) == STRICT_LOW_PART
)
952 memexpr
= XEXP (memexpr
, 0);
953 if (GET_CODE (memexpr
) == SUBREG
)
954 memexpr
= SUBREG_REG (memexpr
);
955 in_reg
= REGNO (memexpr
);
957 if (in_reg
== out_reg
)
964 /* Return true if INSN is an empty asm instruction. */
967 empty_asm_p (rtx insn
)
969 rtx body
= PATTERN (insn
);
972 if (GET_CODE (body
) == ASM_INPUT
)
973 templ
= XSTR (body
, 0);
974 else if (asm_noperands (body
) >= 0)
975 templ
= decode_asm_operands (body
, NULL
, NULL
, NULL
, NULL
, NULL
);
979 return (templ
&& templ
[0] == '\0');
982 /* Insert a NOP immediately before INSN wherever there is a pipeline hazard.
983 LAST_REG records the register set in the last insn and LAST_INSN_CALL
984 records whether the last insn was a call insn. */
987 gr5_avoid_hazard (rtx_insn
*insn
, unsigned int *last_reg
, bool *last_insn_call
)
989 unsigned int dest_reg
= 0;
992 switch (GET_CODE (insn
))
996 *last_insn_call
= true;
1000 /* If this is an empty asm, just skip it. */
1001 if (!empty_asm_p (insn
))
1004 *last_insn_call
= false;
1009 /* If this is an empty asm, just skip it. */
1010 if (empty_asm_p (insn
))
1018 set
= single_set_and_flags (insn
);
1019 if (set
!= NULL_RTX
)
1021 rtx dest
= SET_DEST (set
);
1022 const bool double_p
= GET_MODE_SIZE (GET_MODE (dest
)) > UNITS_PER_WORD
;
1025 if (GET_CODE (SET_SRC (set
)) == MEM
)
1027 memrtx
= XEXP (SET_SRC (set
), 0);
1028 if (GET_CODE (dest
) == STRICT_LOW_PART
)
1029 dest
= XEXP (dest
, 0);
1031 dest_reg
= REGNO (dest
);
1033 /* If this is a DI or DF mode memory to register
1034 copy, then if rd = rs we get
1039 otherwise the order is
1046 unsigned int base_reg
;
1048 if (GET_CODE (memrtx
) == PLUS
)
1049 base_reg
= REGNO (XEXP (memrtx
, 0));
1051 base_reg
= REGNO (memrtx
);
1053 if (dest_reg
!= base_reg
)
1058 else if (GET_CODE (dest
) == MEM
)
1059 memrtx
= XEXP (dest
, 0);
1061 else if (GET_MODE_CLASS (GET_MODE (dest
)) != MODE_CC
)
1063 if (GET_CODE (dest
) == STRICT_LOW_PART
1064 ||GET_CODE (dest
) == ZERO_EXTRACT
)
1065 dest
= XEXP (dest
, 0);
1066 dest_reg
= REGNO (dest
);
1068 if (GET_CODE (SET_SRC (set
)) == REG
)
1070 unsigned int srcreg
= REGNO (SET_SRC (set
));
1072 /* Check for rs := rs, which will be deleted. */
1073 if (srcreg
== dest_reg
)
1076 /* In the case of a DI or DF mode move from register to
1077 register there is overlap if rd = rs + 1 in which case
1078 the order of the copies is reversed :
1083 if (double_p
&& dest_reg
!= srcreg
+ 1)
1088 /* If this is the delay slot of a call insn, any register it sets
1090 if (*last_insn_call
)
1093 /* If the previous insn sets the value of a register, and this insn
1094 uses a base register, check for the pipeline hazard where it is
1095 the same register in each case. */
1096 if (*last_reg
!= 0 && memrtx
!= NULL_RTX
)
1098 unsigned int reg
= 0;
1100 /* Check for an index (original architecture). */
1101 if (GET_CODE (memrtx
) == PLUS
)
1102 reg
= REGNO (XEXP (memrtx
, 0));
1104 /* Check for an MCM target or rs := [rs], in DI or DF mode. */
1105 else if (TARGET_MCM
|| (double_p
&& REGNO (memrtx
) == dest_reg
))
1106 reg
= REGNO (memrtx
);
1108 /* Remove any pipeline hazard by inserting a NOP. */
1109 if (reg
== *last_reg
)
1113 "inserting nop before insn %d\n", INSN_UID (insn
));
1114 emit_insn_after (gen_hazard_nop (), prev_active_insn (insn
));
1115 emit_insn_after (gen_blockage (), insn
);
1119 *last_reg
= dest_reg
;
1122 *last_insn_call
= false;
1125 /* Go through the instruction stream and insert nops where necessary to avoid
1126 pipeline hazards. There are two cases:
1128 1. On the original architecture, it is invalid to set the value of a
1129 (base) register and then use it in an address with a non-zero index
1130 in the next instruction.
1132 2. On the MCM, setting the value of a (base) register and then using
1133 it in address (including with zero index) in the next instruction
1134 will result in a pipeline stall of 3 cycles. */
1137 gr5_hazard_avoidance (void)
1139 unsigned int last_reg
= 0;
1140 bool last_insn_call
= false;
1143 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
1146 rtx pat
= PATTERN (insn
);
1148 if (GET_CODE (pat
) == SEQUENCE
)
1150 for (int i
= 0; i
< XVECLEN (pat
, 0); i
++)
1151 gr5_avoid_hazard (as_a
<rtx_insn
*> (XVECEXP (pat
, 0, i
)),
1152 &last_reg
, &last_insn_call
);
1155 else if (GET_CODE (insn
) == CALL_INSN
)
1157 /* This call is going to get a nop in its delay slot. */
1159 last_insn_call
= false;
1163 gr5_avoid_hazard (insn
, &last_reg
, &last_insn_call
);
1166 else if (GET_CODE (insn
) == BARRIER
)
1170 /* Perform a target-specific pass over the instruction stream. The compiler
1171 will run it at all optimization levels, just after the point at which it
1172 normally does delayed-branch scheduling. */
1177 if (visium_cpu
== PROCESSOR_GR5
)
1178 gr5_hazard_avoidance ();
1182 /* Return true if an argument must be passed by indirect reference. */
1185 visium_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED
,
1186 enum machine_mode mode ATTRIBUTE_UNUSED
,
1188 bool named ATTRIBUTE_UNUSED
)
1190 return type
&& (AGGREGATE_TYPE_P (type
) || TREE_CODE (type
) == VECTOR_TYPE
);
1193 /* Define how arguments are passed.
1195 A range of general registers and floating registers is available
1196 for passing arguments. When the class of registers which an
1197 argument would normally use is exhausted, that argument, is passed
1198 in the overflow region of the stack. No argument is split between
1199 registers and stack.
1201 Arguments of type float or _Complex float go in FP registers if FP
1202 hardware is available. If there is no FP hardware, arguments of
1203 type float go in general registers. All other arguments are passed
1204 in general registers. */
1207 visium_function_arg (cumulative_args_t pcum_v
, enum machine_mode mode
,
1208 const_tree type ATTRIBUTE_UNUSED
,
1209 bool named ATTRIBUTE_UNUSED
)
1212 CUMULATIVE_ARGS
*ca
= get_cumulative_args (pcum_v
);
1214 size
= (GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
1215 if (mode
== VOIDmode
)
1218 /* Scalar or complex single precision floating point arguments are returned
1219 in floating registers. */
1221 && ((GET_MODE_CLASS (mode
) == MODE_FLOAT
1222 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
)
1223 || (GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
1224 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
* 2)))
1226 if (ca
->frcount
+ size
<= MAX_ARGS_IN_FP_REGISTERS
)
1227 return gen_rtx_REG (mode
, FP_ARG_FIRST
+ ca
->frcount
);
1232 if (ca
->grcount
+ size
<= MAX_ARGS_IN_GP_REGISTERS
)
1233 return gen_rtx_REG (mode
, ca
->grcount
+ GP_ARG_FIRST
);
1238 /* Update the summarizer variable pointed to by PCUM_V to advance past an
1239 argument in the argument list. The values MODE, TYPE and NAMED describe
1240 that argument. Once this is done, the variable CUM is suitable for
1241 analyzing the _following_ argument with visium_function_arg. */
1244 visium_function_arg_advance (cumulative_args_t pcum_v
,
1245 enum machine_mode mode
,
1246 const_tree type ATTRIBUTE_UNUSED
,
1249 int size
= (GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
1251 CUMULATIVE_ARGS
*ca
= get_cumulative_args (pcum_v
);
1253 /* Scalar or complex single precision floating point arguments are returned
1254 in floating registers. */
1256 && ((GET_MODE_CLASS (mode
) == MODE_FLOAT
1257 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
)
1258 || (GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
1259 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
* 2)))
1261 if (ca
->frcount
+ size
<= MAX_ARGS_IN_FP_REGISTERS
)
1262 ca
->frcount
+= size
;
1266 ca
->frcount
= MAX_ARGS_IN_FP_REGISTERS
;
1271 /* Everything else goes in a general register, if enough are
1273 if (ca
->grcount
+ size
<= MAX_ARGS_IN_GP_REGISTERS
)
1274 ca
->grcount
+= size
;
1278 ca
->grcount
= MAX_ARGS_IN_GP_REGISTERS
;
1283 ca
->stack_words
+= stack_size
;
1286 /* Specify whether to return the return value in memory. */
1289 visium_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
1291 return (AGGREGATE_TYPE_P (type
) || TREE_CODE (type
) == VECTOR_TYPE
);
1294 /* Define how scalar values are returned. */
1297 visium_function_value_1 (enum machine_mode mode
)
1299 /* Scalar or complex single precision floating point values
1300 are returned in floating register f1. */
1302 && ((GET_MODE_CLASS (mode
) == MODE_FLOAT
1303 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
)
1304 || (GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
1305 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
* 2)))
1306 return gen_rtx_REG (mode
, FP_RETURN_REGNUM
);
1308 /* All others are returned in r1. */
1309 return gen_rtx_REG (mode
, RETURN_REGNUM
);
1312 /* Return an RTX representing the place where a function returns or receives
1313 a value of data type RET_TYPE. */
1316 visium_function_value (const_tree ret_type
,
1317 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1318 bool outgoing ATTRIBUTE_UNUSED
)
1320 return visium_function_value_1 (TYPE_MODE (ret_type
));
1323 /* Return an RTX representing the place where the library function result will
1327 visium_libcall_value (enum machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
1329 return visium_function_value_1 (mode
);
1332 /* Store the anonymous register arguments into the stack so that all the
1333 arguments appear to have been passed consecutively on the stack. */
1336 visium_setup_incoming_varargs (cumulative_args_t pcum_v
,
1337 enum machine_mode mode
,
1339 int *pretend_size ATTRIBUTE_UNUSED
,
1342 cumulative_args_t local_args_so_far
;
1343 CUMULATIVE_ARGS local_copy
;
1344 CUMULATIVE_ARGS
*locargs
;
1345 int gp_saved
, fp_saved
, size
;
1347 /* Create an internal cumulative_args_t pointer to internally define
1348 storage to ensure calling TARGET_FUNCTION_ARG_ADVANCE does not
1349 make global changes. */
1350 local_args_so_far
.p
= &local_copy
;
1351 locargs
= get_cumulative_args (pcum_v
);
1353 #ifdef ENABLE_CHECKING
1354 local_args_so_far
.magic
= CUMULATIVE_ARGS_MAGIC
;
1357 local_copy
.grcount
= locargs
->grcount
;
1358 local_copy
.frcount
= locargs
->frcount
;
1359 local_copy
.stack_words
= locargs
->stack_words
;
1361 /* The caller has advanced ARGS_SO_FAR up to, but not beyond, the last named
1362 argument. Advance a local copy of ARGS_SO_FAR past the last "real" named
1363 argument, to find out how many registers are left over. */
1364 TARGET_FUNCTION_ARG_ADVANCE (local_args_so_far
, mode
, type
, 1);
1366 /* Find how many registers we need to save. */
1367 locargs
= get_cumulative_args (local_args_so_far
);
1368 gp_saved
= MAX_ARGS_IN_GP_REGISTERS
- locargs
->grcount
;
1369 fp_saved
= (TARGET_FPU
? MAX_ARGS_IN_FP_REGISTERS
- locargs
->frcount
: 0);
1370 size
= (gp_saved
* UNITS_PER_WORD
) + (fp_saved
* UNITS_PER_HWFPVALUE
);
1372 if (!no_rtl
&& size
> 0)
1374 /* To avoid negative offsets, which are not valid addressing modes on
1375 the Visium, we create a base register for the pretend args. */
1378 plus_constant (Pmode
, virtual_incoming_args_rtx
, -size
));
1383 = gen_rtx_MEM (BLKmode
,
1384 plus_constant (Pmode
,
1386 fp_saved
* UNITS_PER_HWFPVALUE
));
1387 MEM_NOTRAP_P (mem
) = 1;
1388 set_mem_alias_set (mem
, get_varargs_alias_set ());
1389 move_block_from_reg (locargs
->grcount
+ GP_ARG_FIRST
, mem
, gp_saved
);
1394 rtx mem
= gen_rtx_MEM (BLKmode
, ptr
);
1395 MEM_NOTRAP_P (mem
) = 1;
1396 set_mem_alias_set (mem
, get_varargs_alias_set ());
1397 gcc_assert (UNITS_PER_WORD
== UNITS_PER_HWFPVALUE
);
1398 move_block_from_reg (locargs
->frcount
+ FP_ARG_FIRST
, mem
, fp_saved
);
1402 visium_reg_parm_save_area_size
= size
;
1405 /* Define the `__builtin_va_list' type for the ABI. */
1408 visium_build_builtin_va_list (void)
1410 tree f_ovfl
, f_gbase
, f_fbase
, f_gbytes
, f_fbytes
, record
;
1412 record
= (*lang_hooks
.types
.make_type
) (RECORD_TYPE
);
1413 f_ovfl
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1414 get_identifier ("__overflow_argptr"), ptr_type_node
);
1415 f_gbase
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1416 get_identifier ("__gpr_base"), ptr_type_node
);
1417 f_fbase
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1418 get_identifier ("__fpr_base"), ptr_type_node
);
1419 f_gbytes
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1420 get_identifier ("__gpr_bytes"),
1421 short_unsigned_type_node
);
1422 f_fbytes
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1423 get_identifier ("__fpr_bytes"),
1424 short_unsigned_type_node
);
1426 DECL_FIELD_CONTEXT (f_ovfl
) = record
;
1427 DECL_FIELD_CONTEXT (f_gbase
) = record
;
1428 DECL_FIELD_CONTEXT (f_fbase
) = record
;
1429 DECL_FIELD_CONTEXT (f_gbytes
) = record
;
1430 DECL_FIELD_CONTEXT (f_fbytes
) = record
;
1431 TYPE_FIELDS (record
) = f_ovfl
;
1432 TREE_CHAIN (f_ovfl
) = f_gbase
;
1433 TREE_CHAIN (f_gbase
) = f_fbase
;
1434 TREE_CHAIN (f_fbase
) = f_gbytes
;
1435 TREE_CHAIN (f_gbytes
) = f_fbytes
;
1436 layout_type (record
);
1441 /* Implement `va_start' for varargs and stdarg. */
1444 visium_va_start (tree valist
, rtx nextarg ATTRIBUTE_UNUSED
)
1446 const CUMULATIVE_ARGS
*ca
= &crtl
->args
.info
;
1447 int gp_saved
= MAX_ARGS_IN_GP_REGISTERS
- ca
->grcount
;
1448 int fp_saved
= (TARGET_FPU
? MAX_ARGS_IN_FP_REGISTERS
- ca
->frcount
: 0);
1449 int named_stack_size
= ca
->stack_words
* UNITS_PER_WORD
, offset
;
1450 tree f_ovfl
, f_gbase
, f_fbase
, f_gbytes
, f_fbytes
;
1451 tree ovfl
, gbase
, gbytes
, fbase
, fbytes
, t
;
1453 f_ovfl
= TYPE_FIELDS (va_list_type_node
);
1454 f_gbase
= TREE_CHAIN (f_ovfl
);
1455 f_fbase
= TREE_CHAIN (f_gbase
);
1456 f_gbytes
= TREE_CHAIN (f_fbase
);
1457 f_fbytes
= TREE_CHAIN (f_gbytes
);
1458 ovfl
= build3 (COMPONENT_REF
, TREE_TYPE (f_ovfl
), valist
, f_ovfl
, NULL_TREE
);
1459 gbase
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbase
), valist
, f_gbase
,
1461 fbase
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbase
), valist
, f_fbase
,
1463 gbytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbytes
), valist
, f_gbytes
,
1465 fbytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbytes
), valist
, f_fbytes
,
1468 /* Store the stacked vararg pointer in the OVFL member. */
1469 t
= make_tree (TREE_TYPE (ovfl
), virtual_incoming_args_rtx
);
1470 t
= fold_build_pointer_plus_hwi (t
, named_stack_size
);
1471 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ovfl
), ovfl
, t
);
1472 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1474 /* Store the base address of the GPR save area into GBASE. */
1475 t
= make_tree (TREE_TYPE (gbase
), virtual_incoming_args_rtx
);
1476 offset
= MAX_ARGS_IN_GP_REGISTERS
* UNITS_PER_WORD
;
1477 t
= fold_build_pointer_plus_hwi (t
, -offset
);
1478 t
= build2 (MODIFY_EXPR
, TREE_TYPE (gbase
), gbase
, t
);
1479 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1481 /* Store the base address of the FPR save area into FBASE. */
1484 t
= make_tree (TREE_TYPE (fbase
), virtual_incoming_args_rtx
);
1485 offset
= gp_saved
* UNITS_PER_WORD
1486 + MAX_ARGS_IN_FP_REGISTERS
* UNITS_PER_HWFPVALUE
;
1487 t
= fold_build_pointer_plus_hwi (t
, -offset
);
1488 t
= build2 (MODIFY_EXPR
, TREE_TYPE (fbase
), fbase
, t
);
1489 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1492 /* Fill in the GBYTES member. */
1493 t
= build2 (MODIFY_EXPR
, TREE_TYPE (gbytes
), gbytes
,
1494 size_int (gp_saved
* UNITS_PER_WORD
));
1495 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1497 /* Fill in the FBYTES member. */
1498 t
= build2 (MODIFY_EXPR
, TREE_TYPE (fbytes
),
1499 fbytes
, size_int (fp_saved
* UNITS_PER_HWFPVALUE
));
1500 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1503 /* Implement `va_arg'. */
1506 visium_gimplify_va_arg (tree valist
, tree type
, gimple_seq
*pre_p
,
1509 tree f_ovfl
, f_gbase
, f_fbase
, f_gbytes
, f_fbytes
;
1510 tree ovfl
, base
, bytes
;
1511 HOST_WIDE_INT size
, rsize
;
1512 const bool by_reference_p
1513 = pass_by_reference (NULL
, TYPE_MODE (type
), type
, false);
1514 const bool float_reg_arg_p
1515 = (TARGET_FPU
&& !by_reference_p
1516 && ((GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
1517 && GET_MODE_SIZE (TYPE_MODE (type
)) <= UNITS_PER_HWFPVALUE
)
1518 || (GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_COMPLEX_FLOAT
1519 && (GET_MODE_SIZE (TYPE_MODE (type
))
1520 <= UNITS_PER_HWFPVALUE
* 2))));
1521 const int max_save_area_size
1522 = (float_reg_arg_p
? MAX_ARGS_IN_FP_REGISTERS
* UNITS_PER_HWFPVALUE
1523 : MAX_ARGS_IN_GP_REGISTERS
* UNITS_PER_WORD
);
1525 tree lab_false
, lab_over
, addr
;
1526 tree ptrtype
= build_pointer_type (type
);
1530 t
= visium_gimplify_va_arg (valist
, ptrtype
, pre_p
, post_p
);
1531 return build_va_arg_indirect_ref (t
);
1534 size
= int_size_in_bytes (type
);
1535 rsize
= (size
+ UNITS_PER_WORD
- 1) & -UNITS_PER_WORD
;
1536 f_ovfl
= TYPE_FIELDS (va_list_type_node
);
1537 f_gbase
= TREE_CHAIN (f_ovfl
);
1538 f_fbase
= TREE_CHAIN (f_gbase
);
1539 f_gbytes
= TREE_CHAIN (f_fbase
);
1540 f_fbytes
= TREE_CHAIN (f_gbytes
);
1542 /* We maintain separate pointers and offsets for floating-point and
1543 general registers, but we need similar code in both cases.
1547 BYTES be the number of unused bytes in the register save area.
1548 BASE be the base address of the register save area.
1549 OFFS be the current offset into the register save area. Either
1550 MAX_ARGS_IN_GP_REGISTERS * UNITS_PER_WORD - bytes or
1551 MAX_ARGS_IN_FP_REGISTERS * UNITS_PER_HWFPVALUE - bytes
1552 depending upon whether the argument is in general or floating
1554 ADDR_RTX be the address of the argument.
1555 RSIZE be the size in bytes of the argument.
1556 OVFL be the pointer to the stack overflow area.
1558 The code we want is:
1560 1: if (bytes >= rsize)
1562 3: addr_rtx = base + offs;
1574 addr
= create_tmp_var (ptr_type_node
, "addr");
1575 lab_false
= create_artificial_label (UNKNOWN_LOCATION
);
1576 lab_over
= create_artificial_label (UNKNOWN_LOCATION
);
1577 if (float_reg_arg_p
)
1578 bytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbytes
), unshare_expr (valist
),
1579 f_fbytes
, NULL_TREE
);
1581 bytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbytes
), unshare_expr (valist
),
1582 f_gbytes
, NULL_TREE
);
1584 /* [1] Emit code to branch if bytes < rsize. */
1585 t
= fold_convert (TREE_TYPE (bytes
), size_int (rsize
));
1586 t
= build2 (LT_EXPR
, boolean_type_node
, bytes
, t
);
1587 u
= build1 (GOTO_EXPR
, void_type_node
, lab_false
);
1588 t
= build3 (COND_EXPR
, void_type_node
, t
, u
, NULL_TREE
);
1589 gimplify_and_add (t
, pre_p
);
1591 /* [3] Emit code for: addr_rtx = base + offs, where
1592 offs = max_save_area_size - bytes. */
1593 t
= fold_convert (sizetype
, bytes
);
1594 offs
= build2 (MINUS_EXPR
, sizetype
, size_int (max_save_area_size
), t
);
1595 if (float_reg_arg_p
)
1596 base
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbase
), valist
, f_fbase
,
1599 base
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbase
), valist
, f_gbase
,
1602 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (base
), base
, offs
);
1603 t
= build2 (MODIFY_EXPR
, void_type_node
, addr
, t
);
1604 gimplify_and_add (t
, pre_p
);
1606 /* [4] Emit code for: bytes -= rsize. */
1607 t
= fold_convert (TREE_TYPE (bytes
), size_int (rsize
));
1608 t
= build2 (MINUS_EXPR
, TREE_TYPE (bytes
), bytes
, t
);
1609 t
= build2 (MODIFY_EXPR
, TREE_TYPE (bytes
), bytes
, t
);
1610 gimplify_and_add (t
, pre_p
);
1612 /* [6] Emit code to branch over the else clause, then the label. */
1613 t
= build1 (GOTO_EXPR
, void_type_node
, lab_over
);
1614 gimplify_and_add (t
, pre_p
);
1615 t
= build1 (LABEL_EXPR
, void_type_node
, lab_false
);
1616 gimplify_and_add (t
, pre_p
);
1618 /* [8] Emit code for: bytes = 0. */
1619 t
= fold_convert (TREE_TYPE (bytes
), size_int (0));
1620 t
= build2 (MODIFY_EXPR
, TREE_TYPE (bytes
), unshare_expr (bytes
), t
);
1621 gimplify_and_add (t
, pre_p
);
1623 /* [9] Emit code for: addr_rtx = ovfl. */
1624 ovfl
= build3 (COMPONENT_REF
, TREE_TYPE (f_ovfl
), valist
, f_ovfl
, NULL_TREE
);
1625 t
= build2 (MODIFY_EXPR
, void_type_node
, addr
, ovfl
);
1626 gimplify_and_add (t
, pre_p
);
1628 /* [10] Emit code for: ovfl += rsize. */
1629 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (ovfl
), ovfl
, size_int (rsize
));
1630 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ovfl
), unshare_expr (ovfl
), t
);
1631 gimplify_and_add (t
, pre_p
);
1632 t
= build1 (LABEL_EXPR
, void_type_node
, lab_over
);
1633 gimplify_and_add (t
, pre_p
);
1634 addr
= fold_convert (ptrtype
, addr
);
1636 return build_va_arg_indirect_ref (addr
);
1639 /* Return true if OP is an offset suitable for use as a displacement in the
1640 address of a memory access in mode MODE. */
1643 rtx_ok_for_offset_p (enum machine_mode mode
, rtx op
)
1645 if (!CONST_INT_P (op
) || INTVAL (op
) < 0)
1651 return INTVAL (op
) <= 31;
1654 return (INTVAL (op
) % 2) == 0 && INTVAL (op
) < 63;
1658 return (INTVAL (op
) % 4) == 0 && INTVAL (op
) < 127;
1662 return (INTVAL (op
) % 4) == 0 && INTVAL (op
) < 123;
1669 /* Return whether X is a legitimate memory address for a memory operand
1672 Legitimate addresses are defined in two variants: a strict variant
1673 and a non-strict one. The STRICT parameter chooses which variant
1674 is desired by the caller.
1676 The strict variant is used in the reload pass. It must be defined
1677 so that any pseudo-register that has not been allocated a hard
1678 register is considered a memory reference. This is because in
1679 contexts where some kind of register is required, a
1680 pseudo-register with no hard register must be rejected. For
1681 non-hard registers, the strict variant should look up the
1682 `reg_renumber' array; it should then proceed using the hard
1683 register number in the array, or treat the pseudo as a memory
1684 reference if the array holds `-1'.
1686 The non-strict variant is used in other passes. It must be
1687 defined to accept all pseudo-registers in every context where some
1688 kind of register is required. */
1691 visium_legitimate_address_p (enum machine_mode mode
, rtx x
, bool strict
)
1696 /* If X is base+disp, check that we have an appropriate offset. */
1697 if (GET_CODE (x
) == PLUS
)
1699 if (!rtx_ok_for_offset_p (mode
, XEXP (x
, 1)))
1706 /* Now check the base: it must be either a register or a subreg thereof. */
1707 if (GET_CODE (base
) == SUBREG
)
1708 base
= SUBREG_REG (base
);
1712 regno
= REGNO (base
);
1714 /* For the strict variant, the register must be REGNO_OK_FOR_BASE_P. */
1716 return REGNO_OK_FOR_BASE_P (regno
);
1718 /* For the non-strict variant, the register may also be a pseudo. */
1719 return BASE_REGISTER_P (regno
) || regno
>= FIRST_PSEUDO_REGISTER
;
1722 /* Try machine-dependent ways of modifying an illegitimate address
1723 to be legitimate. If we find one, return the new, valid address.
1724 This macro is used in only one place: `memory_address' in explow.c.
1726 OLDX is the address as it was before break_out_memory_refs was called.
1727 In some cases it is useful to look at this to decide what needs to be done.
1729 MODE and WIN are passed so that this macro can use
1730 GO_IF_LEGITIMATE_ADDRESS.
1732 It is always safe for this macro to do nothing. It exists to recognize
1733 opportunities to optimize the output.
1737 memory (reg + <out of range int>)
1741 base_int = <out of range int> & ~mask
1742 ptr_reg = reg + base_int
1743 memory (ptr_reg + <out of range int> - base_int)
1745 Thus ptr_reg is a base register for a range of addresses,
1746 which should help CSE.
1748 For a 1 byte reference mask is 0x1f
1749 for a 2 byte reference mask is 0x3f
1750 For a 4 byte reference mask is 0x7f
1752 This reflects the indexing range of the processor.
1754 For a > 4 byte reference the mask is 0x7f provided all of the words
1755 can be accessed with the base address obtained. Otherwise a mask
1758 On rare occasions an unaligned base register value with an
1759 unaligned offset is generated. Unaligned offsets are left alone for
1763 visium_legitimize_address (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
1764 enum machine_mode mode
)
1766 if (GET_CODE (x
) == PLUS
1767 && GET_CODE (XEXP (x
, 1)) == CONST_INT
1768 && GET_CODE (XEXP (x
, 0)) == REG
&& mode
!= BLKmode
)
1770 int offset
= INTVAL (XEXP (x
, 1));
1771 int size
= GET_MODE_SIZE (mode
);
1772 int mask
= (size
== 1 ? 0x1f : (size
== 2 ? 0x3f : 0x7f));
1773 int mask1
= (size
== 1 ? 0 : (size
== 2 ? 1 : 3));
1774 int offset_base
= offset
& ~mask
;
1776 /* Check that all of the words can be accessed. */
1777 if (4 < size
&& 0x80 < size
+ offset
- offset_base
)
1778 offset_base
= offset
& ~0x3f;
1779 if (offset_base
!= 0 && offset_base
!= offset
&& (offset
& mask1
) == 0)
1781 rtx ptr_reg
= force_reg (Pmode
,
1782 gen_rtx_PLUS (Pmode
,
1784 GEN_INT (offset_base
)));
1786 return plus_constant (Pmode
, ptr_reg
, offset
- offset_base
);
1793 /* Perform a similar function to visium_legitimize_address, but this time
1794 for reload. Generating new registers is not an option here. Parts
1795 that need reloading are indicated by calling push_reload. */
1798 visium_legitimize_reload_address (rtx x
, enum machine_mode mode
, int opnum
,
1799 int type
, int ind ATTRIBUTE_UNUSED
)
1801 rtx newrtx
, tem
= NULL_RTX
;
1803 if (mode
== BLKmode
)
1806 if (optimize
&& GET_CODE (x
) == PLUS
)
1807 tem
= simplify_binary_operation (PLUS
, GET_MODE (x
), XEXP (x
, 0),
1810 newrtx
= tem
? tem
: x
;
1811 if (GET_CODE (newrtx
) == PLUS
1812 && GET_CODE (XEXP (newrtx
, 1)) == CONST_INT
1813 && GET_CODE (XEXP (newrtx
, 0)) == REG
1814 && BASE_REGISTER_P (REGNO (XEXP (newrtx
, 0))))
1816 int offset
= INTVAL (XEXP (newrtx
, 1));
1817 int size
= GET_MODE_SIZE (mode
);
1818 int mask
= (size
== 1 ? 0x1f : (size
== 2 ? 0x3f : 0x7f));
1819 int mask1
= (size
== 1 ? 0 : (size
== 2 ? 1 : 3));
1820 int offset_base
= offset
& ~mask
;
1822 /* Check that all of the words can be accessed. */
1823 if (4 < size
&& 0x80 < size
+ offset
- offset_base
)
1824 offset_base
= offset
& ~0x3f;
1826 if (offset_base
&& (offset
& mask1
) == 0)
1828 rtx temp
= gen_rtx_PLUS (Pmode
,
1829 XEXP (newrtx
, 0), GEN_INT (offset_base
));
1831 x
= gen_rtx_PLUS (Pmode
, temp
, GEN_INT (offset
- offset_base
));
1832 push_reload (XEXP (x
, 0), 0, &XEXP (x
, 0), 0,
1833 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
,
1834 (enum reload_type
) type
);
1842 /* Return the cost of moving data of mode MODE from a register in class FROM to
1843 one in class TO. A value of 2 is the default; other values are interpreted
1844 relative to that. */
1847 visium_register_move_cost (enum machine_mode mode
, reg_class_t from
,
1850 const int numwords
= (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
) ? 1 : 2;
1852 if (from
== MDB
|| to
== MDB
)
1854 else if (from
== MDC
|| to
== MDC
|| (from
== FP_REGS
) != (to
== FP_REGS
))
1855 return 4 * numwords
;
1857 return 2 * numwords
;
1860 /* Return the cost of moving data of mode MODE between a register of class
1861 CLASS and memory. IN is zero if the value is to be written to memory,
1862 non-zero if it is to be read in. This cost is relative to those in
1863 visium_register_move_cost. */
1866 visium_memory_move_cost (enum machine_mode mode
,
1867 reg_class_t to ATTRIBUTE_UNUSED
,
1870 /* Moving data in can be from PROM and this is expensive. */
1873 if (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
)
1879 /* Moving data out is mostly to RAM and should be cheaper. */
1882 if (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
)
1889 /* Return the relative costs of expression X. */
1892 visium_rtx_costs (rtx x
, int code
, int outer_code ATTRIBUTE_UNUSED
,
1893 int opno ATTRIBUTE_UNUSED
, int *total
,
1894 bool speed ATTRIBUTE_UNUSED
)
1896 enum machine_mode mode
= GET_MODE (x
);
1901 /* Small integers are as cheap as registers. 4-byte values can
1902 be fetched as immediate constants - let's give that the cost
1903 of an extra insn. */
1904 *total
= COSTS_N_INSNS (!satisfies_constraint_J (x
));
1910 *total
= COSTS_N_INSNS (2);
1916 split_double (x
, &high
, &low
);
1919 (!satisfies_constraint_J (high
) + !satisfies_constraint_J (low
));
1924 *total
= COSTS_N_INSNS (3);
1932 *total
= COSTS_N_INSNS (64);
1934 *total
= COSTS_N_INSNS (32);
1940 /* DImode operations are performed directly on the ALU. */
1942 *total
= COSTS_N_INSNS (2);
1944 *total
= COSTS_N_INSNS (1);
1950 /* DImode operations are performed on the EAM instead. */
1952 *total
= COSTS_N_INSNS (3);
1954 *total
= COSTS_N_INSNS (1);
1958 /* This matches the btst pattern. */
1959 if (GET_CODE (XEXP (x
, 0)) == ZERO_EXTRACT
1960 && XEXP (x
, 1) == const0_rtx
1961 && XEXP (XEXP (x
, 0), 1) == const1_rtx
1962 && satisfies_constraint_K (XEXP (XEXP (x
, 0), 2)))
1963 *total
= COSTS_N_INSNS (1);
1971 /* Split a double move of OPERANDS in MODE. */
1974 split_double_move (rtx
*operands
, enum machine_mode mode
)
1978 /* Check register to register with overlap. */
1979 if (GET_CODE (operands
[0]) == REG
1980 && GET_CODE (operands
[1]) == REG
1981 && REGNO (operands
[0]) == REGNO (operands
[1]) + 1)
1984 /* Check memory to register where the base reg overlaps the destination. */
1985 if (GET_CODE (operands
[0]) == REG
&& GET_CODE (operands
[1]) == MEM
)
1987 rtx op
= XEXP (operands
[1], 0);
1989 if (GET_CODE (op
) == SUBREG
)
1990 op
= SUBREG_REG (op
);
1992 if (GET_CODE (op
) == REG
&& REGNO (op
) == REGNO (operands
[0]))
1995 if (GET_CODE (op
) == PLUS
)
1997 rtx x
= XEXP (op
, 0);
1998 rtx y
= XEXP (op
, 1);
2000 if (GET_CODE (x
) == REG
&& REGNO (x
) == REGNO (operands
[0]))
2003 if (GET_CODE (y
) == REG
&& REGNO (y
) == REGNO (operands
[0]))
2010 operands
[2] = operand_subword (operands
[0], 1, 1, mode
);
2011 operands
[3] = operand_subword (operands
[1], 1, 1, mode
);
2012 operands
[4] = operand_subword (operands
[0], 0, 1, mode
);
2013 operands
[5] = operand_subword (operands
[1], 0, 1, mode
);
2017 operands
[2] = operand_subword (operands
[0], 0, 1, mode
);
2018 operands
[3] = operand_subword (operands
[1], 0, 1, mode
);
2019 operands
[4] = operand_subword (operands
[0], 1, 1, mode
);
2020 operands
[5] = operand_subword (operands
[1], 1, 1, mode
);
2024 /* Expand a copysign of OPERANDS in MODE. */
2027 visium_expand_copysign (rtx
*operands
, enum machine_mode mode
)
2029 rtx dest
= operands
[0];
2030 rtx op0
= operands
[1];
2031 rtx op1
= operands
[2];
2032 rtx mask
= force_reg (SImode
, GEN_INT (0x7fffffff));
2035 /* We manually handle SFmode because the abs and neg instructions of
2036 the FPU on the MCM have a non-standard behavior wrt NaNs. */
2037 gcc_assert (mode
== SFmode
);
2039 /* First get all the non-sign bits of OP0. */
2040 if (GET_CODE (op0
) == CONST_DOUBLE
)
2042 if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0
)))
2043 op0
= simplify_unary_operation (ABS
, mode
, op0
, mode
);
2044 if (op0
!= CONST0_RTX (mode
))
2048 REAL_VALUE_FROM_CONST_DOUBLE (rv
, op0
);
2049 REAL_VALUE_TO_TARGET_SINGLE (rv
, l
);
2050 op0
= force_reg (SImode
, GEN_INT (trunc_int_for_mode (l
, SImode
)));
2055 op0
= copy_to_mode_reg (SImode
, gen_lowpart (SImode
, op0
));
2056 op0
= force_reg (SImode
, gen_rtx_AND (SImode
, op0
, mask
));
2059 /* Then get the sign bit of OP1. */
2060 mask
= force_reg (SImode
, gen_rtx_NOT (SImode
, mask
));
2061 op1
= copy_to_mode_reg (SImode
, gen_lowpart (SImode
, op1
));
2062 op1
= force_reg (SImode
, gen_rtx_AND (SImode
, op1
, mask
));
2064 /* Finally OR the two values. */
2065 if (op0
== CONST0_RTX (SFmode
))
2068 x
= force_reg (SImode
, gen_rtx_IOR (SImode
, op0
, op1
));
2070 /* And move the result to the destination. */
2071 emit_insn (gen_rtx_SET (dest
, gen_lowpart (SFmode
, x
)));
2074 /* Expand a cstore of OPERANDS in MODE for EQ/NE/LTU/GTU/GEU/LEU. We generate
2075 the result in the C flag and use the ADC/SUBC instructions to write it into
2076 the destination register.
2078 It would also be possible to implement support for LT/GT/LE/GE by means of
2079 the RFLAG instruction followed by some shifts, but this can pessimize the
2083 visium_expand_int_cstore (rtx
*operands
, enum machine_mode mode
)
2085 enum rtx_code code
= GET_CODE (operands
[1]);
2086 rtx op0
= operands
[0], op1
= operands
[2], op2
= operands
[3], sltu
;
2087 bool reverse
= false;
2093 /* We use a special comparison to get the result in the C flag. */
2094 if (op2
!= const0_rtx
)
2095 op1
= force_reg (mode
, gen_rtx_XOR (mode
, op1
, op2
));
2096 op1
= gen_rtx_NOT (mode
, op1
);
2104 /* The result is naturally in the C flag modulo a couple of tricks. */
2105 code
= reverse_condition (code
);
2108 /* ... fall through ... */
2124 /* We need either a single ADC or a SUBC and a PLUS. */
2125 sltu
= gen_rtx_LTU (SImode
, op1
, op2
);
2129 rtx tmp
= copy_to_mode_reg (SImode
, gen_rtx_NEG (SImode
, sltu
));
2130 emit_insn (gen_add3_insn (op0
, tmp
, const1_rtx
));
2133 emit_insn (gen_rtx_SET (op0
, sltu
));
2136 /* Expand a cstore of OPERANDS in MODE for LT/GT/UNGE/UNLE. We generate the
2137 result in the C flag and use the ADC/SUBC instructions to write it into
2138 the destination register. */
2141 visium_expand_fp_cstore (rtx
*operands
,
2142 enum machine_mode mode ATTRIBUTE_UNUSED
)
2144 enum rtx_code code
= GET_CODE (operands
[1]);
2145 rtx op0
= operands
[0], op1
= operands
[2], op2
= operands
[3], slt
;
2146 bool reverse
= false;
2152 /* The result is naturally in the C flag modulo a couple of tricks. */
2153 code
= reverse_condition_maybe_unordered (code
);
2156 /* ... fall through ... */
2172 /* We need either a single ADC or a SUBC and a PLUS. */
2173 slt
= gen_rtx_LT (SImode
, op1
, op2
);
2177 rtx tmp
= copy_to_mode_reg (SImode
, gen_rtx_NEG (SImode
, slt
));
2178 emit_insn (gen_add3_insn (op0
, tmp
, const1_rtx
));
2181 emit_insn (gen_rtx_SET (op0
, slt
));
2184 /* Split a compare-and-store with CODE, operands OP2 and OP3, combined with
2185 operation with OP_CODE, operands OP0 and OP1. */
2188 visium_split_cstore (enum rtx_code op_code
, rtx op0
, rtx op1
,
2189 enum rtx_code code
, rtx op2
, rtx op3
)
2191 enum machine_mode cc_mode
= visium_select_cc_mode (code
, op2
, op3
);
2193 /* If a FP cstore was reversed, then it was originally UNGE/UNLE. */
2194 if (cc_mode
== CCFPEmode
&& (op_code
== NEG
|| op_code
== MINUS
))
2197 rtx flags
= gen_rtx_REG (cc_mode
, FLAGS_REGNUM
);
2198 rtx x
= gen_rtx_COMPARE (cc_mode
, op2
, op3
);
2199 x
= gen_rtx_SET (flags
, x
);
2202 x
= gen_rtx_fmt_ee (code
, SImode
, flags
, const0_rtx
);
2208 x
= gen_rtx_NEG (SImode
, x
);
2212 x
= gen_rtx_fmt_ee (op_code
, SImode
, op1
, x
);
2218 rtx pat
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (2));
2219 XVECEXP (pat
, 0, 0) = gen_rtx_SET (op0
, x
);
2220 flags
= gen_rtx_REG (CCmode
, FLAGS_REGNUM
);
2221 XVECEXP (pat
, 0, 1) = gen_rtx_CLOBBER (VOIDmode
, flags
);
2224 visium_flags_exposed
= true;
2227 /* Generate a call to a library function to move BYTES_RTX bytes from SRC with
2228 address SRC_REG to DST with address DST_REG in 4-byte chunks. */
2231 expand_block_move_4 (rtx dst
, rtx dst_reg
, rtx src
, rtx src_reg
, rtx bytes_rtx
)
2233 const rtx sym
= gen_rtx_SYMBOL_REF (Pmode
, "__long_int_memcpy");
2234 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2235 unsigned int rem
= bytes
% 4;
2242 emit_move_insn (regno_reg_rtx
[1], dst_reg
);
2243 emit_move_insn (regno_reg_rtx
[2], src_reg
);
2244 emit_move_insn (regno_reg_rtx
[3], bytes_rtx
);
2246 insn
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (8));
2247 XVECEXP (insn
, 0, 0)
2248 = gen_rtx_SET (replace_equiv_address_nv (dst
, regno_reg_rtx
[1]),
2249 replace_equiv_address_nv (src
, regno_reg_rtx
[2]));
2250 XVECEXP (insn
, 0, 1) = gen_rtx_USE (VOIDmode
, regno_reg_rtx
[3]);
2251 for (i
= 1; i
<= 6; i
++)
2252 XVECEXP (insn
, 0, 1 + i
)
2253 = gen_rtx_CLOBBER (VOIDmode
, regno_reg_rtx
[i
]);
2257 emit_library_call (sym
, LCT_NORMAL
, VOIDmode
, 3, dst_reg
, Pmode
, src_reg
,
2259 convert_to_mode (TYPE_MODE (sizetype
),
2260 GEN_INT (bytes
>> 2),
2261 TYPE_UNSIGNED (sizetype
)),
2262 TYPE_MODE (sizetype
));
2266 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2267 src
= replace_equiv_address_nv (src
, src_reg
);
2272 emit_move_insn (adjust_address_nv (dst
, HImode
, bytes
),
2273 adjust_address_nv (src
, HImode
, bytes
));
2279 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2280 adjust_address_nv (src
, QImode
, bytes
));
2283 /* Generate a call to a library function to move BYTES_RTX bytes from SRC with
2284 address SRC_REG to DST with address DST_REG in 2-bytes chunks. */
2287 expand_block_move_2 (rtx dst
, rtx dst_reg
, rtx src
, rtx src_reg
, rtx bytes_rtx
)
2289 const rtx sym
= gen_rtx_SYMBOL_REF (Pmode
, "__wrd_memcpy");
2290 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2291 unsigned int rem
= bytes
% 2;
2293 emit_library_call (sym
, LCT_NORMAL
, VOIDmode
, 3, dst_reg
, Pmode
, src_reg
,
2295 convert_to_mode (TYPE_MODE (sizetype
),
2296 GEN_INT (bytes
>> 1),
2297 TYPE_UNSIGNED (sizetype
)),
2298 TYPE_MODE (sizetype
));
2302 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2303 src
= replace_equiv_address_nv (src
, src_reg
);
2306 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2307 adjust_address_nv (src
, QImode
, bytes
));
2310 /* Generate a call to a library function to move BYTES_RTX bytes from address
2311 SRC_REG to address DST_REG in 1-byte chunks. */
2314 expand_block_move_1 (rtx dst_reg
, rtx src_reg
, rtx bytes_rtx
)
2316 const rtx sym
= gen_rtx_SYMBOL_REF (Pmode
, "__byt_memcpy");
2318 emit_library_call (sym
, LCT_NORMAL
, VOIDmode
, 3, dst_reg
, Pmode
,
2320 convert_to_mode (TYPE_MODE (sizetype
),
2322 TYPE_UNSIGNED (sizetype
)),
2323 TYPE_MODE (sizetype
));
2326 /* Generate a call to a library function to set BYTES_RTX bytes of DST with
2327 address DST_REG to VALUE_RTX in 4-byte chunks. */
2330 expand_block_set_4 (rtx dst
, rtx dst_reg
, rtx value_rtx
, rtx bytes_rtx
)
2332 const rtx sym
= gen_rtx_SYMBOL_REF (Pmode
, "__long_int_memset");
2333 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2334 unsigned int rem
= bytes
% 4;
2336 value_rtx
= convert_to_mode (Pmode
, value_rtx
, 1);
2337 emit_library_call (sym
, LCT_NORMAL
, VOIDmode
, 3, dst_reg
, Pmode
,
2339 convert_to_mode (TYPE_MODE (sizetype
),
2340 GEN_INT (bytes
>> 2),
2341 TYPE_UNSIGNED (sizetype
)),
2342 TYPE_MODE (sizetype
));
2346 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2351 if (CONST_INT_P (value_rtx
))
2353 const unsigned HOST_WIDE_INT value
= UINTVAL (value_rtx
) & 0xff;
2354 emit_move_insn (adjust_address_nv (dst
, HImode
, bytes
),
2355 gen_int_mode ((value
<< 8) | value
, HImode
));
2359 rtx temp
= convert_to_mode (QImode
, value_rtx
, 1);
2360 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
), temp
);
2361 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
+ 1), temp
);
2368 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2369 convert_to_mode (QImode
, value_rtx
, 1));
2372 /* Generate a call to a library function to set BYTES_RTX bytes of DST with
2373 address DST_REG to VALUE_RTX in 2-byte chunks. */
2376 expand_block_set_2 (rtx dst
, rtx dst_reg
, rtx value_rtx
, rtx bytes_rtx
)
2378 const rtx sym
= gen_rtx_SYMBOL_REF (Pmode
, "__wrd_memset");
2379 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2380 unsigned int rem
= bytes
% 2;
2382 value_rtx
= convert_to_mode (Pmode
, value_rtx
, 1);
2383 emit_library_call (sym
, LCT_NORMAL
, VOIDmode
, 3, dst_reg
, Pmode
,
2385 convert_to_mode (TYPE_MODE (sizetype
),
2386 GEN_INT (bytes
>> 1),
2387 TYPE_UNSIGNED (sizetype
)),
2388 TYPE_MODE (sizetype
));
2392 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2395 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2396 convert_to_mode (QImode
, value_rtx
, 1));
2399 /* Generate a call to a library function to set BYTES_RTX bytes at address
2400 DST_REG to VALUE_RTX in 1-byte chunks. */
2403 expand_block_set_1 (rtx dst_reg
, rtx value_rtx
, rtx bytes_rtx
)
2405 const rtx sym
= gen_rtx_SYMBOL_REF (Pmode
, "__byt_memset");
2407 value_rtx
= convert_to_mode (Pmode
, value_rtx
, 1);
2408 emit_library_call (sym
, LCT_NORMAL
, VOIDmode
, 3, dst_reg
, Pmode
,
2410 convert_to_mode (TYPE_MODE (sizetype
),
2412 TYPE_UNSIGNED (sizetype
)),
2413 TYPE_MODE (sizetype
));
2416 /* Expand string/block move operations.
2418 operands[0] is the pointer to the destination.
2419 operands[1] is the pointer to the source.
2420 operands[2] is the number of bytes to move.
2421 operands[3] is the alignment.
2423 Return 1 upon success, 0 otherwise. */
2426 visium_expand_block_move (rtx
*operands
)
2428 rtx dst
= operands
[0];
2429 rtx src
= operands
[1];
2430 rtx bytes_rtx
= operands
[2];
2431 rtx align_rtx
= operands
[3];
2432 const int align
= INTVAL (align_rtx
);
2433 rtx dst_reg
, src_reg
;
2434 tree dst_expr
, src_expr
;
2436 /* We only handle a fixed number of bytes for now. */
2437 if (!CONST_INT_P (bytes_rtx
) || INTVAL (bytes_rtx
) <= 0)
2440 /* Copy the addresses into scratch registers. */
2441 dst_reg
= copy_addr_to_reg (XEXP (dst
, 0));
2442 src_reg
= copy_addr_to_reg (XEXP (src
, 0));
2444 /* Move the data with the appropriate granularity. */
2446 expand_block_move_4 (dst
, dst_reg
, src
, src_reg
, bytes_rtx
);
2447 else if (align
>= 2)
2448 expand_block_move_2 (dst
, dst_reg
, src
, src_reg
, bytes_rtx
);
2450 expand_block_move_1 (dst_reg
, src_reg
, bytes_rtx
);
2452 /* Since DST and SRC are passed to a libcall, mark the corresponding
2453 tree EXPR as addressable. */
2454 dst_expr
= MEM_EXPR (dst
);
2455 src_expr
= MEM_EXPR (src
);
2457 mark_addressable (dst_expr
);
2459 mark_addressable (src_expr
);
2464 /* Expand string/block set operations.
2466 operands[0] is the pointer to the destination.
2467 operands[1] is the number of bytes to set.
2468 operands[2] is the source value.
2469 operands[3] is the alignment.
2471 Return 1 upon success, 0 otherwise. */
2474 visium_expand_block_set (rtx
*operands
)
2476 rtx dst
= operands
[0];
2477 rtx bytes_rtx
= operands
[1];
2478 rtx value_rtx
= operands
[2];
2479 rtx align_rtx
= operands
[3];
2480 const int align
= INTVAL (align_rtx
);
2484 /* We only handle a fixed number of bytes for now. */
2485 if (!CONST_INT_P (bytes_rtx
) || INTVAL (bytes_rtx
) <= 0)
2488 /* Copy the address into a scratch register. */
2489 dst_reg
= copy_addr_to_reg (XEXP (dst
, 0));
2491 /* Set the data with the appropriate granularity. */
2493 expand_block_set_4 (dst
, dst_reg
, value_rtx
, bytes_rtx
);
2494 else if (align
>= 2)
2495 expand_block_set_2 (dst
, dst_reg
, value_rtx
, bytes_rtx
);
2497 expand_block_set_1 (dst_reg
, value_rtx
, bytes_rtx
);
2499 /* Since DST is passed to a libcall, mark the corresponding
2500 tree EXPR as addressable. */
2501 dst_expr
= MEM_EXPR (dst
);
2503 mark_addressable (dst_expr
);
2508 /* Initialize a trampoline. M_TRAMP is an RTX for the memory block for the
2509 trampoline, FNDECL is the FUNCTION_DECL for the nested function and
2510 STATIC_CHAIN is an RTX for the static chain value that should be passed
2511 to the function when it is called. */
2514 visium_trampoline_init (rtx m_tramp
, tree fndecl
, rtx static_chain
)
2516 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2517 rtx addr
= XEXP (m_tramp
, 0);
2519 /* The trampoline initialization sequence is:
2521 moviu r9,%u FUNCTION
2522 movil r9,%l FUNCTION
2527 We don't use r0 as the destination register of the branch because we want
2528 the Branch Pre-decode Logic of the GR6 to use the Address Load Array to
2529 predict the branch target. */
2531 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 0)),
2532 plus_constant (SImode
,
2533 expand_shift (RSHIFT_EXPR
, SImode
, fnaddr
,
2537 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 4)),
2538 plus_constant (SImode
,
2539 expand_and (SImode
, fnaddr
, GEN_INT (0xffff),
2543 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 8)),
2544 plus_constant (SImode
,
2545 expand_shift (RSHIFT_EXPR
, SImode
,
2550 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 12)),
2551 gen_int_mode (0xff892404, SImode
));
2553 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 16)),
2554 plus_constant (SImode
,
2555 expand_and (SImode
, static_chain
,
2556 GEN_INT (0xffff), NULL_RTX
),
2559 emit_library_call (gen_rtx_SYMBOL_REF (Pmode
, "__set_trampoline_parity"),
2560 LCT_NORMAL
, VOIDmode
, 1, addr
, SImode
);
2563 /* Return true if the current function must have and use a frame pointer. */
2566 visium_frame_pointer_required (void)
2568 /* The frame pointer is required if the function isn't leaf to be able to
2569 do manual stack unwinding. */
2573 /* If the stack pointer is dynamically modified in the function, it cannot
2574 serve as the frame pointer. */
2575 if (!crtl
->sp_is_unchanging
)
2578 /* If the function receives nonlocal gotos, it needs to save the frame
2579 pointer in the nonlocal_goto_save_area object. */
2580 if (cfun
->has_nonlocal_label
)
2583 /* The frame also needs to be established in some special cases. */
2584 if (visium_frame_needed
)
2590 /* Profiling support. Just a call to MCOUNT is needed. No labelled counter
2591 location is involved. Proper support for __builtin_return_address is also
2592 required, which is fairly straightforward provided a frame gets created. */
2595 visium_profile_hook (void)
2597 visium_frame_needed
= true;
2598 emit_library_call (gen_rtx_SYMBOL_REF (Pmode
, "mcount"), LCT_NORMAL
,
2602 /* A C expression whose value is RTL representing the address in a stack frame
2603 where the pointer to the caller's frame is stored. Assume that FRAMEADDR is
2604 an RTL expression for the address of the stack frame itself.
2606 If you don't define this macro, the default is to return the value of
2607 FRAMEADDR--that is, the stack frame address is also the address of the stack
2608 word that points to the previous frame. */
2611 visium_dynamic_chain_address (rtx frame
)
2613 /* This is the default, but we need to make sure the frame gets created. */
2614 visium_frame_needed
= true;
2618 /* A C expression whose value is RTL representing the value of the return
2619 address for the frame COUNT steps up from the current frame, after the
2620 prologue. FRAMEADDR is the frame pointer of the COUNT frame, or the frame
2621 pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' is
2624 The value of the expression must always be the correct address when COUNT is
2625 zero, but may be `NULL_RTX' if there is not way to determine the return
2626 address of other frames. */
2629 visium_return_addr_rtx (int count
, rtx frame ATTRIBUTE_UNUSED
)
2631 /* Dont try to compute anything other than frame zero. */
2635 visium_frame_needed
= true;
2637 gen_frame_mem (Pmode
, plus_constant (Pmode
, hard_frame_pointer_rtx
, 4));
2640 /* Helper function for EH_RETURN_HANDLER_RTX. Return the RTX representing a
2641 location in which to store the address of an exception handler to which we
2645 visium_eh_return_handler_rtx (void)
2648 = gen_frame_mem (SImode
, plus_constant (Pmode
, hard_frame_pointer_rtx
, 4));
2649 MEM_VOLATILE_P (mem
) = 1;
2653 static struct machine_function
*
2654 visium_init_machine_status (void)
2656 return ggc_cleared_alloc
<machine_function
> ();
2659 /* The per-function data machinery is needed to indicate when a frame
2663 visium_init_expanders (void)
2665 init_machine_status
= visium_init_machine_status
;
2668 /* Given a comparison code (EQ, NE, etc.) and the operands of a COMPARE,
2669 return the mode to be used for the comparison. */
2672 visium_select_cc_mode (enum rtx_code code
, rtx op0
, rtx op1
)
2674 if (GET_MODE_CLASS (GET_MODE (op0
)) == MODE_FLOAT
)
2694 /* These 2 comparison codes are not supported. */
2702 if (op1
!= const0_rtx
)
2705 switch (GET_CODE (op0
))
2713 /* The V flag may be set differently from a COMPARE with zero.
2714 The consequence is that a comparison operator testing V must
2715 be turned into another operator not testing V and yielding
2716 the same result for a comparison with zero. That's possible
2717 for GE/LT which become NC/NS respectively, but not for GT/LE
2718 for which the altered operator doesn't exist on the Visium. */
2722 /* This is a btst, the result is in C instead of Z. */
2726 /* This is a degenerate case, typically an uninitialized variable. */
2727 gcc_assert (op0
== constm1_rtx
);
2737 /* Pretend that the flags are set as for a COMPARE with zero.
2738 That's mostly true, except for the 2 right shift insns that
2739 will set the C flag. But the C flag is relevant only for
2740 the unsigned comparison operators and they are eliminated
2741 when applied to a comparison with zero. */
2749 /* Split a compare-and-branch with CODE, operands OP0 and OP1, and LABEL. */
2752 visium_split_cbranch (enum rtx_code code
, rtx op0
, rtx op1
, rtx label
)
2754 enum machine_mode cc_mode
= visium_select_cc_mode (code
, op0
, op1
);
2755 rtx flags
= gen_rtx_REG (cc_mode
, FLAGS_REGNUM
);
2757 rtx x
= gen_rtx_COMPARE (cc_mode
, op0
, op1
);
2758 x
= gen_rtx_SET (flags
, x
);
2761 x
= gen_rtx_fmt_ee (code
, VOIDmode
, flags
, const0_rtx
);
2762 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
, gen_rtx_LABEL_REF (Pmode
, label
),
2764 x
= gen_rtx_SET (pc_rtx
, x
);
2767 visium_flags_exposed
= true;
2770 /* Branch instructions on the Visium.
2772 Setting aside the interrupt-handling specific instructions, the ISA has
2773 two branch instructions: BRR and BRA. The former is used to implement
2774 short branches (+/- 2^17) within functions and its target is encoded in
2775 the instruction. The latter is used to implement all the other types
2776 of control flow changes and its target might not be statically known
2777 or even easily predictable at run time. Here's a complete summary of
2778 the patterns that generate a BRA instruction:
2788 Among these patterns, only the return (5) and the long branch (6) can be
2789 conditional; all the other patterns are always unconditional.
2791 The following algorithm can be used to identify the pattern for which
2792 the BRA instruction was generated and work out its target:
2794 A. If the source is r21 and the destination is r0, this is a return (5)
2795 and the target is the caller (i.e. the value of r21 on function's
2798 B. If the source is rN, N != 21 and the destination is r0, this is either
2799 an indirect jump or a table jump (1, 2) and the target is not easily
2802 C. If the source is rN, N != 21 and the destination is r21, this is a call
2803 (3) and the target is given by the preceding MOVIL/MOVIU pair for rN,
2804 unless this is an indirect call in which case the target is not easily
2807 D. If the source is rN, N != 21 and the destination is also rN, this is
2808 either a sibling call or a trampoline (4, 7) and the target is given
2809 by the preceding MOVIL/MOVIU pair for rN.
2811 E. If the source is r21 and the destination is also r21, this is a long
2812 branch (6) and the target is given by the preceding MOVIL/MOVIU pair
2815 The other combinations are not used. This implementation has been devised
2816 to accommodate the branch predictor of the GR6 but is used unconditionally
2817 by the compiler, i.e. including for earlier processors. */
2819 /* Output a conditional/unconditional branch to LABEL. COND is the string
2820 condition. INSN is the instruction. */
2823 output_branch (rtx label
, const char *cond
, rtx_insn
*insn
)
2829 operands
[0] = label
;
2831 /* If the length of the instruction is greater than 8, then this is a
2832 long branch and we need to work harder to emit it properly. */
2833 if (get_attr_length (insn
) > 8)
2837 /* If the link register has been saved, then we use it. */
2838 if (current_function_saves_lr ())
2840 operands
[1] = regno_reg_rtx
[LINK_REGNUM
];
2844 /* Or else, if the long-branch register isn't live, we use it. */
2845 else if (!df_regs_ever_live_p (long_branch_regnum
))
2847 operands
[1] = regno_reg_rtx
[long_branch_regnum
];
2851 /* Otherwise, we will use the long-branch register but we need to
2852 spill it to the stack and reload it at the end. We should have
2853 reserved the LR slot for this purpose. */
2856 operands
[1] = regno_reg_rtx
[long_branch_regnum
];
2858 gcc_assert (current_function_has_lr_slot ());
2861 /* First emit the spill to the stack:
2864 write.l [1](sp),reg */
2869 rtx_insn
*delay
= NEXT_INSN (insn
);
2873 final_scan_insn (delay
, asm_out_file
, optimize
, 0, &seen
);
2874 PATTERN (delay
) = gen_blockage ();
2875 INSN_CODE (delay
) = -1;
2878 if (current_function_saves_fp ())
2879 output_asm_insn ("write.l 1(sp),%1", operands
);
2881 output_asm_insn ("write.l (sp),%1", operands
);
2884 /* Then emit the core sequence:
2890 We don't use r0 as the destination register of the branch because we
2891 want the Branch Pre-decode Logic of the GR6 to use the Address Load
2892 Array to predict the branch target. */
2893 output_asm_insn ("moviu %1,%%u %0", operands
);
2894 output_asm_insn ("movil %1,%%l %0", operands
);
2895 strcpy (str
, "bra ");
2897 strcat (str
, ",%1,%1");
2900 strcat (str
, "\t\t;long branch");
2901 output_asm_insn (str
, operands
);
2903 /* Finally emit the reload:
2905 read.l reg,[1](sp) */
2908 if (current_function_saves_fp ())
2909 output_asm_insn (" read.l %1,1(sp)", operands
);
2911 output_asm_insn (" read.l %1,(sp)", operands
);
2915 /* Or else, if the label is PC, then this is a return. */
2916 else if (label
== pc_rtx
)
2918 strcpy (str
, "bra ");
2920 strcat (str
, ",r21,r0%#\t\t;return");
2921 output_asm_insn (str
, operands
);
2924 /* Otherwise, this is a short branch. */
2927 strcpy (str
, "brr ");
2929 strcat (str
, ",%0%#");
2930 output_asm_insn (str
, operands
);
2936 /* Output an unconditional branch to LABEL. INSN is the instruction. */
2939 output_ubranch (rtx label
, rtx_insn
*insn
)
2941 return output_branch (label
, "tr", insn
);
2944 /* Output a conditional branch to LABEL. CODE is the comparison code.
2945 CC_MODE is the mode of the CC register. REVERSED is non-zero if we
2946 should reverse the sense of the comparison. INSN is the instruction. */
2949 output_cbranch (rtx label
, enum rtx_code code
, enum machine_mode cc_mode
,
2950 int reversed
, rtx_insn
*insn
)
2956 if (cc_mode
== CCFPmode
|| cc_mode
== CCFPEmode
)
2957 code
= reverse_condition_maybe_unordered (code
);
2959 code
= reverse_condition (code
);
2965 if (cc_mode
== CC_BTSTmode
)
2972 if (cc_mode
== CC_BTSTmode
)
2979 if (cc_mode
== CC_NOOVmode
)
2990 if (cc_mode
== CCFPmode
|| cc_mode
== CCFPEmode
)
2997 if (cc_mode
== CCFPmode
|| cc_mode
== CCFPEmode
)
2999 else if (cc_mode
== CC_NOOVmode
)
3045 /* These 2 comparison codes are not supported. */
3052 return output_branch (label
, cond
, insn
);
3055 /* Helper function for PRINT_OPERAND (STREAM, X, CODE). Output to stdio
3056 stream FILE the assembler syntax for an instruction operand OP subject
3057 to the modifier LETTER. */
3060 print_operand (FILE *file
, rtx op
, int letter
)
3065 /* Output an insn in a delay slot. */
3067 visium_indent_opcode
= 1;
3069 fputs ("\n\t nop", file
);
3073 /* Print LS 8 bits of operand. */
3074 fprintf (file
, HOST_WIDE_INT_PRINT_UNSIGNED
, UINTVAL (op
) & 0xff);
3078 /* Print LS 16 bits of operand. */
3079 fprintf (file
, HOST_WIDE_INT_PRINT_UNSIGNED
, UINTVAL (op
) & 0xffff);
3083 /* Print MS 16 bits of operand. */
3085 HOST_WIDE_INT_PRINT_UNSIGNED
, (UINTVAL (op
) >> 16) & 0xffff);
3089 /* It's either a register or zero. */
3090 if (GET_CODE (op
) == REG
)
3091 fputs (reg_names
[REGNO (op
)], file
);
3093 fputs (reg_names
[0], file
);
3097 /* It's either a FP register or zero. */
3098 if (GET_CODE (op
) == REG
)
3099 fputs (reg_names
[REGNO (op
)], file
);
3101 fputs (reg_names
[FP_FIRST_REGNUM
], file
);
3105 switch (GET_CODE (op
))
3109 fputs (reg_names
[REGNO (op
) + 1], file
);
3111 fputs (reg_names
[REGNO (op
)], file
);
3117 output_addr_const (file
, op
);
3121 visium_output_address (file
, GET_MODE (op
), XEXP (op
, 0));
3125 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (op
));
3129 asm_fprintf (file
, "%LL%d", CODE_LABEL_NUMBER (op
));
3133 print_operand (file
, XEXP (op
, 1), letter
);
3137 fatal_insn ("illegal operand ", op
);
3141 /* Output to stdio stream FILE the assembler syntax for an instruction operand
3142 that is a memory reference in MODE and whose address is ADDR. */
3145 visium_output_address (FILE *file
, enum machine_mode mode
, rtx addr
)
3147 switch (GET_CODE (addr
))
3151 fprintf (file
, "(%s)", reg_names
[true_regnum (addr
)]);
3156 rtx x
= XEXP (addr
, 0), y
= XEXP (addr
, 1);
3158 switch (GET_CODE (x
))
3162 if (CONST_INT_P (y
))
3164 unsigned int regno
= true_regnum (x
);
3165 HOST_WIDE_INT val
= INTVAL (y
);
3183 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
"(%s)", val
,
3187 fatal_insn ("illegal operand address (1)", addr
);
3191 if (CONSTANT_P (x
) && CONSTANT_P (y
))
3192 output_addr_const (file
, addr
);
3194 fatal_insn ("illegal operand address (2)", addr
);
3204 output_addr_const (file
, addr
);
3208 if (NOTE_KIND (addr
) != NOTE_INSN_DELETED_LABEL
)
3209 fatal_insn ("illegal operand address (3)", addr
);
3213 asm_fprintf (file
, "%LL%d", CODE_LABEL_NUMBER (addr
));
3217 fatal_insn ("illegal operand address (4)", addr
);
3222 /* Helper function for PRINT_OPERAND_ADDRESS (STREAM, X). Output to stdio
3223 stream FILE the assembler syntax for an instruction operand that is a
3224 memory reference whose address is ADDR. */
3227 print_operand_address (FILE *file
, rtx addr
)
3229 visium_output_address (file
, QImode
, addr
);
3232 /* The Visium stack frames look like:
3234 Before call After call
3235 +-----------------------+ +-----------------------+
3237 high | previous | | previous |
3238 mem | frame | | frame |
3240 +-----------------------+ +-----------------------+
3242 | arguments on stack | | arguments on stack |
3244 SP+0->+-----------------------+ +-----------------------+
3245 | reg parm save area, |
3246 | only created for |
3247 | variable argument |
3249 +-----------------------+
3251 | register save area |
3253 +-----------------------+
3257 FP+8->+-----------------------+
3259 FP+4->+-----------------------+
3261 FP+0->+-----------------------+
3263 | alloca allocations |
3265 +-----------------------+
3267 low | arguments on stack |
3269 SP+0->+-----------------------+
3272 1) The "reg parm save area" does not exist for non variable argument fns.
3273 2) The FP register is not saved if `frame_pointer_needed' is zero and it
3274 is not altered in the current function.
3275 3) The return address is not saved if there is no frame pointer and the
3276 current function is leaf.
3277 4) If the return address is not saved and the static chain register is
3278 live in the function, we allocate the return address slot to be able
3279 to spill the register for a long branch. */
3281 /* Define the register classes for local purposes. */
3282 enum reg_type
{ general
, mdb
, mdc
, floating
, last_type
};
3284 #define GET_REG_TYPE(regno) \
3285 (GP_REGISTER_P (regno) ? general : \
3286 (regno) == MDB_REGNUM ? mdb : \
3287 (regno) == MDC_REGNUM ? mdc : \
3290 /* First regno of each register type. */
3291 const int first_regno
[last_type
] = {0, MDB_REGNUM
, MDC_REGNUM
, FP_FIRST_REGNUM
};
3293 /* Size in bytes of each register type. */
3294 const int reg_type_size
[last_type
] = {4, 8, 4, 4};
3296 /* Structure to be filled in by visium_compute_frame_size. */
3297 struct visium_frame_info
3299 unsigned int save_area_size
; /* # bytes in the reg parm save area. */
3300 unsigned int reg_size1
; /* # bytes to store first block of regs. */
3301 unsigned int reg_size2
; /* # bytes to store second block of regs. */
3302 unsigned int max_reg1
; /* max. regno in first block */
3303 unsigned int var_size
; /* # bytes that variables take up. */
3304 unsigned int save_fp
; /* Nonzero if fp must be saved. */
3305 unsigned int save_lr
; /* Nonzero if lr must be saved. */
3306 unsigned int lr_slot
; /* Nonzero if the lr slot is needed. */
3307 unsigned int combine
; /* Nonzero if we can combine the allocation of
3308 variables and regs. */
3309 unsigned int interrupt
; /* Nonzero if the function is an interrupt
3311 unsigned int mask
[last_type
]; /* Masks of saved regs: gp, mdb, mdc, fp */
3314 /* Current frame information calculated by visium_compute_frame_size. */
3315 static struct visium_frame_info current_frame_info
;
3317 /* Accessor for current_frame_info.save_fp. */
3320 current_function_saves_fp (void)
3322 return current_frame_info
.save_fp
!= 0;
3325 /* Accessor for current_frame_info.save_lr. */
3328 current_function_saves_lr (void)
3330 return current_frame_info
.save_lr
!= 0;
3333 /* Accessor for current_frame_info.lr_slot. */
3336 current_function_has_lr_slot (void)
3338 return current_frame_info
.lr_slot
!= 0;
3341 /* Return non-zero if register REGNO needs to be saved in the frame. */
3344 visium_save_reg_p (int interrupt
, int regno
)
3348 case HARD_FRAME_POINTER_REGNUM
:
3349 /* This register is call-saved but handled specially. */
3353 /* This register is fixed but can be modified. */
3358 /* These registers are fixed and hold the interrupt context. */
3359 return (interrupt
!= 0);
3362 /* The other fixed registers are either immutable or special. */
3363 if (fixed_regs
[regno
])
3372 if (df_regs_ever_live_p (regno
))
3375 else if (call_used_regs
[regno
])
3378 /* To save mdb requires two temporary registers. To save mdc or
3379 any of the floating registers requires one temporary
3380 register. If this is an interrupt routine, the temporary
3381 registers need to be saved as well. These temporary registers
3382 are call used, so we only need deal with the case of leaf
3384 if (regno
== PROLOGUE_TMP_REGNUM
)
3386 if (df_regs_ever_live_p (MDB_REGNUM
)
3387 || df_regs_ever_live_p (MDC_REGNUM
))
3390 for (int i
= FP_FIRST_REGNUM
; i
<= FP_LAST_REGNUM
; i
++)
3391 if (df_regs_ever_live_p (i
))
3395 else if (regno
== PROLOGUE_TMP_REGNUM
+ 1)
3397 if (df_regs_ever_live_p (MDB_REGNUM
))
3402 return df_regs_ever_live_p (regno
) && !call_used_regs
[regno
];
3405 /* Compute the frame size required by the function. This function is called
3406 during the reload pass and also by visium_expand_prologue. */
3409 visium_compute_frame_size (int size
)
3411 const int save_area_size
= visium_reg_parm_save_area_size
;
3412 const int var_size
= VISIUM_STACK_ALIGN (size
);
3414 = frame_pointer_needed
|| df_regs_ever_live_p (HARD_FRAME_POINTER_REGNUM
);
3415 const int save_lr
= frame_pointer_needed
|| !crtl
->is_leaf
;
3416 const int lr_slot
= !save_lr
&& df_regs_ever_live_p (long_branch_regnum
);
3417 const int local_frame_offset
3418 = (save_fp
+ save_lr
+ lr_slot
) * UNITS_PER_WORD
;
3419 const int interrupt
= visium_interrupt_function_p ();
3420 unsigned int mask
[last_type
];
3429 memset (mask
, 0, last_type
* sizeof (unsigned int));
3431 /* The registers may need stacking in 2 blocks since only 32 32-bit words
3432 can be indexed from a given base address. */
3433 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
3435 if (visium_save_reg_p (interrupt
, regno
))
3437 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3438 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3439 int nbytes
= reg_type_size
[reg_type
];
3441 if (reg_size1
+ nbytes
> 32 * UNITS_PER_WORD
)
3444 reg_size1
+= nbytes
;
3446 mask
[reg_type
] |= mask_bit
;
3450 for (regno
= max_reg1
+ 1; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
3452 if (visium_save_reg_p (interrupt
, regno
))
3454 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3455 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3456 int nbytes
= reg_type_size
[reg_type
];
3458 reg_size2
+= nbytes
;
3459 mask
[reg_type
] |= mask_bit
;
3463 reg_size
= reg_size2
? reg_size2
: reg_size1
;
3464 combine
= (local_frame_offset
+ var_size
+ reg_size
) <= 32 * UNITS_PER_WORD
;
3466 = local_frame_offset
+ var_size
+ reg_size2
+ reg_size1
+ save_area_size
;
3468 current_frame_info
.save_area_size
= save_area_size
;
3469 current_frame_info
.reg_size1
= reg_size1
;
3470 current_frame_info
.max_reg1
= max_reg1
;
3471 current_frame_info
.reg_size2
= reg_size2
;
3472 current_frame_info
.var_size
= var_size
;
3473 current_frame_info
.save_fp
= save_fp
;
3474 current_frame_info
.save_lr
= save_lr
;
3475 current_frame_info
.lr_slot
= lr_slot
;
3476 current_frame_info
.combine
= combine
;
3477 current_frame_info
.interrupt
= interrupt
;
3479 memcpy (current_frame_info
.mask
, mask
, last_type
* sizeof (unsigned int));
3484 /* Helper function for INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET). Define
3485 the offset between two registers, one to be eliminated, and the other its
3486 replacement, at the start of a routine. */
3489 visium_initial_elimination_offset (int from
, int to ATTRIBUTE_UNUSED
)
3491 const int frame_size
= visium_compute_frame_size (get_frame_size ());
3492 const int save_fp
= current_frame_info
.save_fp
;
3493 const int save_lr
= current_frame_info
.save_lr
;
3494 const int lr_slot
= current_frame_info
.lr_slot
;
3495 const int local_frame_offset
3496 = (save_fp
+ save_lr
+ lr_slot
) * UNITS_PER_WORD
;
3499 if (from
== FRAME_POINTER_REGNUM
)
3500 offset
= local_frame_offset
;
3501 else if (from
== ARG_POINTER_REGNUM
)
3502 offset
= frame_size
;
3509 /* For an interrupt handler, we may be saving call-clobbered registers.
3510 Say the epilogue uses these in addition to the link register. */
3513 visium_epilogue_uses (int regno
)
3515 if (regno
== LINK_REGNUM
)
3518 if (reload_completed
)
3520 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3521 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3523 return (current_frame_info
.mask
[reg_type
] & mask_bit
) != 0;
3529 /* Wrapper around emit_insn that sets RTX_FRAME_RELATED_P on the insn. */
3532 emit_frame_insn (rtx x
)
3535 RTX_FRAME_RELATED_P (x
) = 1;
3539 /* Allocate ALLOC bytes on the stack and save the registers LOW_REGNO to
3540 HIGH_REGNO at OFFSET from the stack pointer. */
3543 visium_save_regs (int alloc
, int offset
, int low_regno
, int high_regno
)
3545 /* If this is an interrupt handler function, then mark the register
3546 stores as volatile. This will prevent the instruction scheduler
3547 from scrambling the order of register saves. */
3548 const int volatile_p
= current_frame_info
.interrupt
;
3551 /* Allocate the stack space. */
3552 emit_frame_insn (gen_addsi3_flags (stack_pointer_rtx
, stack_pointer_rtx
,
3555 for (regno
= low_regno
; regno
<= high_regno
; regno
++)
3557 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3558 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3561 if (current_frame_info
.mask
[reg_type
] & mask_bit
)
3563 offset
-= reg_type_size
[reg_type
];
3569 = gen_frame_mem (SImode
,
3570 plus_constant (Pmode
,
3571 stack_pointer_rtx
, offset
));
3572 MEM_VOLATILE_P (mem
) = volatile_p
;
3573 emit_frame_insn (gen_movsi (mem
, gen_rtx_REG (SImode
, regno
)));
3579 rtx tmp
= gen_rtx_REG (DImode
, PROLOGUE_TMP_REGNUM
);
3581 = gen_frame_mem (DImode
,
3582 plus_constant (Pmode
,
3583 stack_pointer_rtx
, offset
));
3584 rtx reg
= gen_rtx_REG (DImode
, regno
);
3585 MEM_VOLATILE_P (mem
) = volatile_p
;
3586 emit_insn (gen_movdi (tmp
, reg
));
3587 /* Do not generate CFI if in interrupt handler. */
3589 emit_insn (gen_movdi (mem
, tmp
));
3592 insn
= emit_frame_insn (gen_movdi (mem
, tmp
));
3593 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3594 gen_rtx_SET (mem
, reg
));
3601 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
);
3603 = gen_frame_mem (SImode
,
3604 plus_constant (Pmode
,
3605 stack_pointer_rtx
, offset
));
3606 rtx reg
= gen_rtx_REG (SImode
, regno
);
3607 MEM_VOLATILE_P (mem
) = volatile_p
;
3608 emit_insn (gen_movsi (tmp
, reg
));
3609 insn
= emit_frame_insn (gen_movsi (mem
, tmp
));
3610 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3611 gen_rtx_SET (mem
, reg
));
3617 rtx tmp
= gen_rtx_REG (SFmode
, PROLOGUE_TMP_REGNUM
);
3619 = gen_frame_mem (SFmode
,
3620 plus_constant (Pmode
,
3621 stack_pointer_rtx
, offset
));
3622 rtx reg
= gen_rtx_REG (SFmode
, regno
);
3623 MEM_VOLATILE_P (mem
) = volatile_p
;
3624 emit_insn (gen_movsf (tmp
, reg
));
3625 insn
= emit_frame_insn (gen_movsf (mem
, tmp
));
3626 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3627 gen_rtx_SET (mem
, reg
));
3638 /* This function generates the code for function entry. */
3641 visium_expand_prologue (void)
3643 const int frame_size
= visium_compute_frame_size (get_frame_size ());
3644 const int save_area_size
= current_frame_info
.save_area_size
;
3645 const int reg_size1
= current_frame_info
.reg_size1
;
3646 const int max_reg1
= current_frame_info
.max_reg1
;
3647 const int reg_size2
= current_frame_info
.reg_size2
;
3648 const int var_size
= current_frame_info
.var_size
;
3649 const int save_fp
= current_frame_info
.save_fp
;
3650 const int save_lr
= current_frame_info
.save_lr
;
3651 const int lr_slot
= current_frame_info
.lr_slot
;
3652 const int local_frame_offset
3653 = (save_fp
+ save_lr
+ lr_slot
) * UNITS_PER_WORD
;
3654 const int combine
= current_frame_info
.combine
;
3659 /* Save the frame size for future references. */
3660 visium_frame_size
= frame_size
;
3662 if (flag_stack_usage_info
)
3663 current_function_static_stack_size
= frame_size
;
3665 /* If the registers have to be stacked in 2 blocks, stack the first one. */
3668 visium_save_regs (reg_size1
+ save_area_size
, reg_size1
, 0, max_reg1
);
3669 reg_size
= reg_size2
;
3670 first_reg
= max_reg1
+ 1;
3671 fsize
= local_frame_offset
+ var_size
+ reg_size2
;
3675 reg_size
= reg_size1
;
3677 fsize
= local_frame_offset
+ var_size
+ reg_size1
+ save_area_size
;
3680 /* If we can't combine register stacking with variable allocation, partially
3681 allocate and stack the (remaining) registers now. */
3682 if (reg_size
&& !combine
)
3683 visium_save_regs (fsize
- local_frame_offset
- var_size
, reg_size
,
3684 first_reg
, FIRST_PSEUDO_REGISTER
- 1);
3686 /* If we can combine register stacking with variable allocation, fully
3687 allocate and stack the (remaining) registers now. */
3688 if (reg_size
&& combine
)
3689 visium_save_regs (fsize
, local_frame_offset
+ var_size
+ reg_size
,
3690 first_reg
, FIRST_PSEUDO_REGISTER
- 1);
3692 /* Otherwise space may still need to be allocated for the variables. */
3695 const int alloc_size
= reg_size
? local_frame_offset
+ var_size
: fsize
;
3697 if (alloc_size
> 65535)
3699 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
), insn
;
3700 emit_insn (gen_movsi (tmp
, GEN_INT (alloc_size
)));
3701 insn
= emit_frame_insn (gen_subsi3_flags (stack_pointer_rtx
,
3704 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3705 gen_rtx_SET (stack_pointer_rtx
,
3706 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
3707 GEN_INT (-alloc_size
))));
3710 emit_frame_insn (gen_addsi3_flags (stack_pointer_rtx
,
3712 GEN_INT (-alloc_size
)));
3716 emit_frame_insn (gen_movsi (gen_frame_mem (SImode
, stack_pointer_rtx
),
3717 hard_frame_pointer_rtx
));
3719 if (frame_pointer_needed
)
3720 emit_frame_insn (gen_stack_save ());
3726 /* Normally the frame pointer and link register get saved via
3731 Indexing off sp rather than fp to store the link register
3732 avoids presenting the instruction scheduler with an initial
3733 pipeline hazard. If however the frame is needed for eg.
3734 __builtin_return_address which needs to retrieve the saved
3735 value of the link register from the stack at fp + 4 then
3736 indexing from sp can confuse the dataflow, causing the link
3737 register to be retrieved before it has been saved. */
3738 if (cfun
->machine
->frame_needed
)
3739 base_rtx
= hard_frame_pointer_rtx
;
3741 base_rtx
= stack_pointer_rtx
;
3743 mem
= gen_frame_mem (SImode
,
3744 plus_constant (Pmode
,
3745 base_rtx
, save_fp
* UNITS_PER_WORD
));
3746 emit_frame_insn (gen_movsi (mem
, gen_rtx_REG (SImode
, LINK_REGNUM
)));
3750 static GTY(()) rtx cfa_restores
;
3752 /* Queue a REG_CFA_RESTORE note until next stack manipulation insn. */
3755 visium_add_cfa_restore_note (rtx reg
)
3757 cfa_restores
= alloc_reg_note (REG_CFA_RESTORE
, reg
, cfa_restores
);
3760 /* Add queued REG_CFA_RESTORE notes to INSN, if any. */
3763 visium_add_queued_cfa_restore_notes (rtx insn
)
3768 for (last
= cfa_restores
; XEXP (last
, 1); last
= XEXP (last
, 1))
3770 XEXP (last
, 1) = REG_NOTES (insn
);
3771 REG_NOTES (insn
) = cfa_restores
;
3772 cfa_restores
= NULL_RTX
;
3775 /* Restore the registers LOW_REGNO to HIGH_REGNO from the save area at OFFSET
3776 from the stack pointer and pop DEALLOC bytes off the stack. */
3779 visium_restore_regs (int dealloc
, int offset
, int high_regno
, int low_regno
)
3781 /* If this is an interrupt handler function, then mark the register
3782 restores as volatile. This will prevent the instruction scheduler
3783 from scrambling the order of register restores. */
3784 const int volatile_p
= current_frame_info
.interrupt
;
3785 int r30_offset
= -1;
3788 for (regno
= high_regno
; regno
>= low_regno
; --regno
)
3790 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3791 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3793 if (current_frame_info
.mask
[reg_type
] & mask_bit
)
3798 /* Postpone restoring the interrupted context registers
3799 until last, since they need to be preceded by a dsi. */
3802 else if (regno
== 30)
3803 r30_offset
= offset
;
3807 = gen_frame_mem (SImode
,
3808 plus_constant (Pmode
,
3811 rtx reg
= gen_rtx_REG (SImode
, regno
);
3812 MEM_VOLATILE_P (mem
) = volatile_p
;
3813 emit_insn (gen_movsi (reg
, mem
));
3814 visium_add_cfa_restore_note (reg
);
3820 rtx tmp
= gen_rtx_REG (DImode
, PROLOGUE_TMP_REGNUM
);
3822 = gen_frame_mem (DImode
,
3823 plus_constant (Pmode
,
3824 stack_pointer_rtx
, offset
));
3825 rtx reg
= gen_rtx_REG (DImode
, regno
);
3826 MEM_VOLATILE_P (mem
) = volatile_p
;
3827 emit_insn (gen_movdi (tmp
, mem
));
3828 emit_insn (gen_movdi (reg
, tmp
));
3829 /* Do not generate CFI if in interrupt handler. */
3831 visium_add_cfa_restore_note (reg
);
3837 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
);
3839 = gen_frame_mem (SImode
,
3840 plus_constant (Pmode
,
3841 stack_pointer_rtx
, offset
));
3842 rtx reg
= gen_rtx_REG (SImode
, regno
);
3843 MEM_VOLATILE_P (mem
) = volatile_p
;
3844 emit_insn (gen_movsi (tmp
, mem
));
3845 emit_insn (gen_movsi (reg
, tmp
));
3846 visium_add_cfa_restore_note (reg
);
3852 rtx tmp
= gen_rtx_REG (SFmode
, PROLOGUE_TMP_REGNUM
);
3854 = gen_frame_mem (SFmode
,
3855 plus_constant (Pmode
,
3856 stack_pointer_rtx
, offset
));
3857 rtx reg
= gen_rtx_REG (SFmode
, regno
);
3858 MEM_VOLATILE_P (mem
) = volatile_p
;
3859 emit_insn (gen_movsf (tmp
, mem
));
3860 emit_insn (gen_movsf (reg
, tmp
));
3861 visium_add_cfa_restore_note (reg
);
3869 offset
+= reg_type_size
[reg_type
];
3873 /* If the interrupted context needs to be restored, precede the
3874 restores of r29 and r30 by a dsi. */
3875 if (r30_offset
>= 0)
3877 emit_insn (gen_dsi ());
3878 emit_move_insn (gen_rtx_REG (SImode
, 30),
3879 gen_frame_mem (SImode
,
3880 plus_constant (Pmode
,
3883 emit_move_insn (gen_rtx_REG (SImode
, 29),
3884 gen_frame_mem (SImode
,
3885 plus_constant (Pmode
,
3890 /* Deallocate the stack space. */
3891 rtx insn
= emit_frame_insn (gen_stack_pop (GEN_INT (dealloc
)));
3892 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3893 gen_rtx_SET (stack_pointer_rtx
,
3894 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
3895 GEN_INT (dealloc
))));
3896 visium_add_queued_cfa_restore_notes (insn
);
3899 /* This function generates the code for function exit. */
3902 visium_expand_epilogue (void)
3904 const int save_area_size
= current_frame_info
.save_area_size
;
3905 const int reg_size1
= current_frame_info
.reg_size1
;
3906 const int max_reg1
= current_frame_info
.max_reg1
;
3907 const int reg_size2
= current_frame_info
.reg_size2
;
3908 const int var_size
= current_frame_info
.var_size
;
3909 const int restore_fp
= current_frame_info
.save_fp
;
3910 const int restore_lr
= current_frame_info
.save_lr
;
3911 const int lr_slot
= current_frame_info
.lr_slot
;
3912 const int local_frame_offset
3913 = (restore_fp
+ restore_lr
+ lr_slot
) * UNITS_PER_WORD
;
3914 const int combine
= current_frame_info
.combine
;
3919 /* Do not bother restoring the stack pointer if it hasn't been changed in
3920 the function since it was saved _after_ the allocation of the frame. */
3921 if (!crtl
->sp_is_unchanging
)
3922 emit_insn (gen_stack_restore ());
3924 /* Restore the frame pointer if necessary. The usual code would be:
3929 but for the MCM this constitutes a stall/hazard so it is changed to:
3934 if the stack pointer has actually been restored. */
3939 if (TARGET_MCM
&& !crtl
->sp_is_unchanging
)
3940 src
= gen_frame_mem (SImode
, hard_frame_pointer_rtx
);
3942 src
= gen_frame_mem (SImode
, stack_pointer_rtx
);
3944 rtx insn
= emit_frame_insn (gen_movsi (hard_frame_pointer_rtx
, src
));
3945 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
3946 gen_rtx_SET (stack_pointer_rtx
,
3947 hard_frame_pointer_rtx
));
3948 visium_add_cfa_restore_note (hard_frame_pointer_rtx
);
3951 /* Restore the link register if necessary. */
3954 rtx mem
= gen_frame_mem (SImode
,
3955 plus_constant (Pmode
,
3957 restore_fp
* UNITS_PER_WORD
));
3958 rtx reg
= gen_rtx_REG (SImode
, LINK_REGNUM
);
3959 emit_insn (gen_movsi (reg
, mem
));
3960 visium_add_cfa_restore_note (reg
);
3963 /* If we have two blocks of registers, deal with the second one first. */
3966 reg_size
= reg_size2
;
3967 last_reg
= max_reg1
+ 1;
3968 fsize
= local_frame_offset
+ var_size
+ reg_size2
;
3972 reg_size
= reg_size1
;
3974 fsize
= local_frame_offset
+ var_size
+ reg_size1
+ save_area_size
;
3977 /* If the variable allocation could be combined with register stacking,
3978 restore the (remaining) registers and fully deallocate now. */
3979 if (reg_size
&& combine
)
3980 visium_restore_regs (fsize
, local_frame_offset
+ var_size
,
3981 FIRST_PSEUDO_REGISTER
- 1, last_reg
);
3983 /* Otherwise deallocate the variables first. */
3986 const int pop_size
= reg_size
? local_frame_offset
+ var_size
: fsize
;
3989 if (pop_size
> 65535)
3991 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
);
3992 emit_move_insn (tmp
, GEN_INT (pop_size
));
3993 insn
= emit_frame_insn (gen_stack_pop (tmp
));
3996 insn
= emit_frame_insn (gen_stack_pop (GEN_INT (pop_size
)));
3997 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3998 gen_rtx_SET (stack_pointer_rtx
,
3999 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
4000 GEN_INT (pop_size
))));
4001 visium_add_queued_cfa_restore_notes (insn
);
4004 /* If the variable allocation couldn't be combined with register stacking,
4005 restore the (remaining) registers now and partially deallocate. */
4006 if (reg_size
&& !combine
)
4007 visium_restore_regs (fsize
- local_frame_offset
- var_size
, 0,
4008 FIRST_PSEUDO_REGISTER
- 1, last_reg
);
4010 /* If the first block of registers has yet to be restored, do it now. */
4012 visium_restore_regs (reg_size1
+ save_area_size
, 0, max_reg1
, 0);
4014 /* If this is an exception return, make the necessary stack adjustment. */
4015 if (crtl
->calls_eh_return
)
4016 emit_insn (gen_stack_pop (EH_RETURN_STACKADJ_RTX
));
4019 /* Return true if it is appropriate to emit `return' instructions in the
4020 body of a function. */
4023 visium_can_use_return_insn_p (void)
4025 return reload_completed
4026 && visium_frame_size
== 0
4027 && !visium_interrupt_function_p ();
4030 /* Return the register class required for an intermediate register used to
4031 copy a register of RCLASS from/to X. If no such intermediate register is
4032 required, return NO_REGS. If more than one such intermediate register is
4033 required, describe the one that is closest in the copy chain to the reload
4037 visium_secondary_reload (bool in_p ATTRIBUTE_UNUSED
, rtx x
,
4039 enum machine_mode mode ATTRIBUTE_UNUSED
,
4040 secondary_reload_info
*sri ATTRIBUTE_UNUSED
)
4042 int regno
= true_regnum (x
);
4044 /* For MDB, MDC and FP_REGS, a general register is needed for a move to
4046 if (regno
== -1 && (rclass
== MDB
|| rclass
== MDC
|| rclass
== FP_REGS
))
4047 return GENERAL_REGS
;
4049 /* Moves between MDB, MDC and FP_REGS also require a general register. */
4050 else if (((regno
== R_MDB
|| regno
== R_MDC
) && rclass
== FP_REGS
)
4051 || (FP_REGISTER_P (regno
) && (rclass
== MDB
|| rclass
== MDC
)))
4052 return GENERAL_REGS
;
4054 /* Finally an (unlikely ?) move between MDB and MDC needs a general reg. */
4055 else if ((regno
== R_MDB
&& rclass
== MDC
)
4056 || (rclass
== MDB
&& regno
== R_MDC
))
4057 return GENERAL_REGS
;
4062 /* Return true if pseudos that have been assigned to registers of RCLASS
4063 would likely be spilled because registers of RCLASS are needed for
4067 visium_class_likely_spilled_p (reg_class_t rclass ATTRIBUTE_UNUSED
)
4069 /* Return false for classes R1, R2 and R3, which are intended to be used
4070 only in the source code in conjunction with block move instructions. */
4074 /* Return the register number if OP is a REG or a SUBREG of a REG, and
4075 INVALID_REGNUM in all the other cases. */
4078 reg_or_subreg_regno (rtx op
)
4082 if (GET_CODE (op
) == REG
)
4084 else if (GET_CODE (op
) == SUBREG
&& GET_CODE (SUBREG_REG (op
)) == REG
)
4086 if (REGNO (SUBREG_REG (op
)) < FIRST_PSEUDO_REGISTER
)
4087 regno
= subreg_regno (op
);
4089 regno
= REGNO (SUBREG_REG (op
));
4092 regno
= INVALID_REGNUM
;
4097 #include "gt-visium.h"