1 /* Output routines for Visium.
2 Copyright (C) 2002-2019 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/>. */
21 #define IN_TARGET_CODE 1
25 #include "coretypes.h"
30 #include "gimple-expr.h"
34 #include "stringpool.h"
41 #include "diagnostic-core.h"
44 #include "fold-const.h"
45 #include "stor-layout.h"
49 #include "insn-attr.h"
53 #include "langhooks.h"
55 #include "tm-constrs.h"
57 #include "tree-pass.h"
61 /* This file should be included last. */
62 #include "target-def.h"
64 /* Enumeration of indexes into machine_libfunc_table. */
65 enum machine_libfunc_index
75 MLTI_set_trampoline_parity
,
80 struct GTY(()) machine_libfuncs
85 /* The table of Visium-specific libfuncs. */
86 static GTY(()) struct machine_libfuncs visium_libfuncs
;
88 #define vlt visium_libfuncs.table
90 /* Accessor macros for visium_libfuncs. */
91 #define long_int_memcpy_libfunc (vlt[MLTI_long_int_memcpy])
92 #define wrd_memcpy_libfunc (vlt[MLTI_wrd_memcpy])
93 #define byt_memcpy_libfunc (vlt[MLTI_byt_memcpy])
94 #define long_int_memset_libfunc (vlt[MLTI_long_int_memset])
95 #define wrd_memset_libfunc (vlt[MLTI_wrd_memset])
96 #define byt_memset_libfunc (vlt[MLTI_byt_memset])
97 #define set_trampoline_parity_libfunc (vlt[MLTI_set_trampoline_parity])
99 /* Machine specific function data. */
100 struct GTY (()) machine_function
102 /* Size of the frame of the function. */
105 /* Size of the reg parm save area, non-zero only for functions with variable
106 argument list. We cannot use the crtl->args.pretend_args_size machinery
107 for this purpose because this size is added to virtual_incoming_args_rtx
108 to give the location of the first parameter passed by the caller on the
109 stack and virtual_incoming_args_rtx is also the location of the first
110 parameter on the stack. So crtl->args.pretend_args_size can be non-zero
111 only if the first non-register named parameter is not passed entirely on
112 the stack and this runs afoul of the need to have a reg parm save area
113 even with a variable argument list starting on the stack because of the
114 separate handling of general and floating-point registers. */
115 int reg_parm_save_area_size
;
117 /* True if we have created an rtx which relies on the frame pointer. */
120 /* True if we have exposed the flags register. From this moment on, we
121 cannot generate simple operations for integer registers. We could
122 use reload_completed for this purpose, but this would cripple the
123 postreload CSE and GCSE passes which run before postreload split. */
127 #define visium_frame_size cfun->machine->frame_size
128 #define visium_reg_parm_save_area_size cfun->machine->reg_parm_save_area_size
129 #define visium_frame_needed cfun->machine->frame_needed
130 #define visium_flags_exposed cfun->machine->flags_exposed
132 /* 1 if the next opcode is to be specially indented. */
133 int visium_indent_opcode
= 0;
135 /* Register number used for long branches when LR isn't available. It
136 must be a call-used register since it isn't saved on function entry.
137 We do not care whether the branch is predicted or not on the GR6,
138 given how unlikely it is to have a long branch in a leaf function. */
139 static unsigned int long_branch_regnum
= 31;
141 static tree
visium_handle_interrupt_attr (tree
*, tree
, tree
, int, bool *);
142 static inline bool current_function_saves_fp (void);
143 static inline bool current_function_saves_lr (void);
144 static inline bool current_function_has_lr_slot (void);
146 /* Supported attributes:
147 interrupt -- specifies this function is an interrupt handler. */
148 static const struct attribute_spec visium_attribute_table
[] =
150 /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
151 affects_type_identity, handler, exclude } */
152 { "interrupt", 0, 0, true, false, false, false, visium_handle_interrupt_attr
,
154 { NULL
, 0, 0, false, false, false, false, NULL
, NULL
},
157 static struct machine_function
*visium_init_machine_status (void);
159 /* Target hooks and TARGET_INITIALIZER */
161 static bool visium_pass_by_reference (cumulative_args_t
, machine_mode
,
164 static rtx
visium_function_arg (cumulative_args_t
, machine_mode
,
167 static void visium_function_arg_advance (cumulative_args_t
, machine_mode
,
170 static bool visium_return_in_memory (const_tree
, const_tree fntype
);
172 static rtx
visium_function_value (const_tree
, const_tree fn_decl_or_type
,
175 static rtx
visium_libcall_value (machine_mode
, const_rtx
);
177 static void visium_setup_incoming_varargs (cumulative_args_t
,
181 static void visium_va_start (tree valist
, rtx nextarg
);
183 static tree
visium_gimplify_va_arg (tree
, tree
, gimple_seq
*, gimple_seq
*);
185 static bool visium_function_ok_for_sibcall (tree
, tree
);
187 static bool visium_frame_pointer_required (void);
189 static tree
visium_build_builtin_va_list (void);
191 static rtx_insn
*visium_md_asm_adjust (vec
<rtx
> &, vec
<rtx
> &,
193 vec
<rtx
> &, HARD_REG_SET
&);
195 static bool visium_legitimate_constant_p (machine_mode
, rtx
);
197 static bool visium_legitimate_address_p (machine_mode
, rtx
, bool);
199 static bool visium_print_operand_punct_valid_p (unsigned char);
200 static void visium_print_operand (FILE *, rtx
, int);
201 static void visium_print_operand_address (FILE *, machine_mode
, rtx
);
203 static void visium_conditional_register_usage (void);
205 static rtx
visium_legitimize_address (rtx
, rtx
, machine_mode
);
207 static reg_class_t
visium_secondary_reload (bool, rtx
, reg_class_t
,
209 secondary_reload_info
*);
211 static bool visium_class_likely_spilled_p (reg_class_t
);
213 static void visium_trampoline_init (rtx
, tree
, rtx
);
215 static int visium_issue_rate (void);
217 static int visium_adjust_priority (rtx_insn
*, int);
219 static int visium_adjust_cost (rtx_insn
*, int, rtx_insn
*, int, unsigned int);
221 static int visium_register_move_cost (machine_mode
, reg_class_t
,
224 static int visium_memory_move_cost (machine_mode
, reg_class_t
, bool);
226 static bool visium_rtx_costs (rtx
, machine_mode
, int, int, int *, bool);
228 static void visium_option_override (void);
230 static void visium_init_libfuncs (void);
232 static unsigned int visium_reorg (void);
234 static unsigned int visium_hard_regno_nregs (unsigned int, machine_mode
);
236 static bool visium_hard_regno_mode_ok (unsigned int, machine_mode
);
238 static bool visium_modes_tieable_p (machine_mode
, machine_mode
);
240 static bool visium_can_change_mode_class (machine_mode
, machine_mode
,
243 static HOST_WIDE_INT
visium_constant_alignment (const_tree
, HOST_WIDE_INT
);
245 /* Setup the global target hooks structure. */
247 #undef TARGET_MAX_ANCHOR_OFFSET
248 #define TARGET_MAX_ANCHOR_OFFSET 31
250 #undef TARGET_PASS_BY_REFERENCE
251 #define TARGET_PASS_BY_REFERENCE visium_pass_by_reference
253 #undef TARGET_FUNCTION_ARG
254 #define TARGET_FUNCTION_ARG visium_function_arg
256 #undef TARGET_FUNCTION_ARG_ADVANCE
257 #define TARGET_FUNCTION_ARG_ADVANCE visium_function_arg_advance
259 #undef TARGET_RETURN_IN_MEMORY
260 #define TARGET_RETURN_IN_MEMORY visium_return_in_memory
262 #undef TARGET_FUNCTION_VALUE
263 #define TARGET_FUNCTION_VALUE visium_function_value
265 #undef TARGET_LIBCALL_VALUE
266 #define TARGET_LIBCALL_VALUE visium_libcall_value
268 #undef TARGET_SETUP_INCOMING_VARARGS
269 #define TARGET_SETUP_INCOMING_VARARGS visium_setup_incoming_varargs
271 #undef TARGET_EXPAND_BUILTIN_VA_START
272 #define TARGET_EXPAND_BUILTIN_VA_START visium_va_start
274 #undef TARGET_BUILD_BUILTIN_VA_LIST
275 #define TARGET_BUILD_BUILTIN_VA_LIST visium_build_builtin_va_list
277 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
278 #define TARGET_GIMPLIFY_VA_ARG_EXPR visium_gimplify_va_arg
280 #undef TARGET_LEGITIMATE_CONSTANT_P
281 #define TARGET_LEGITIMATE_CONSTANT_P visium_legitimate_constant_p
284 #define TARGET_LRA_P hook_bool_void_false
286 #undef TARGET_LEGITIMATE_ADDRESS_P
287 #define TARGET_LEGITIMATE_ADDRESS_P visium_legitimate_address_p
289 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
290 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P visium_print_operand_punct_valid_p
292 #undef TARGET_PRINT_OPERAND
293 #define TARGET_PRINT_OPERAND visium_print_operand
295 #undef TARGET_PRINT_OPERAND_ADDRESS
296 #define TARGET_PRINT_OPERAND_ADDRESS visium_print_operand_address
298 #undef TARGET_ATTRIBUTE_TABLE
299 #define TARGET_ATTRIBUTE_TABLE visium_attribute_table
301 #undef TARGET_ADDRESS_COST
302 #define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
304 #undef TARGET_STRICT_ARGUMENT_NAMING
305 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
307 #undef TARGET_SCHED_ISSUE_RATE
308 #define TARGET_SCHED_ISSUE_RATE visium_issue_rate
310 #undef TARGET_SCHED_ADJUST_PRIORITY
311 #define TARGET_SCHED_ADJUST_PRIORITY visium_adjust_priority
313 #undef TARGET_SCHED_ADJUST_COST
314 #define TARGET_SCHED_ADJUST_COST visium_adjust_cost
316 #undef TARGET_MEMORY_MOVE_COST
317 #define TARGET_MEMORY_MOVE_COST visium_memory_move_cost
319 #undef TARGET_REGISTER_MOVE_COST
320 #define TARGET_REGISTER_MOVE_COST visium_register_move_cost
322 #undef TARGET_RTX_COSTS
323 #define TARGET_RTX_COSTS visium_rtx_costs
325 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
326 #define TARGET_FUNCTION_OK_FOR_SIBCALL visium_function_ok_for_sibcall
328 #undef TARGET_FRAME_POINTER_REQUIRED
329 #define TARGET_FRAME_POINTER_REQUIRED visium_frame_pointer_required
331 #undef TARGET_SECONDARY_RELOAD
332 #define TARGET_SECONDARY_RELOAD visium_secondary_reload
334 #undef TARGET_CLASS_LIKELY_SPILLED_P
335 #define TARGET_CLASS_LIKELY_SPILLED_P visium_class_likely_spilled_p
337 #undef TARGET_LEGITIMIZE_ADDRESS
338 #define TARGET_LEGITIMIZE_ADDRESS visium_legitimize_address
340 #undef TARGET_OPTION_OVERRIDE
341 #define TARGET_OPTION_OVERRIDE visium_option_override
343 #undef TARGET_INIT_LIBFUNCS
344 #define TARGET_INIT_LIBFUNCS visium_init_libfuncs
346 #undef TARGET_CONDITIONAL_REGISTER_USAGE
347 #define TARGET_CONDITIONAL_REGISTER_USAGE visium_conditional_register_usage
349 #undef TARGET_TRAMPOLINE_INIT
350 #define TARGET_TRAMPOLINE_INIT visium_trampoline_init
352 #undef TARGET_MD_ASM_ADJUST
353 #define TARGET_MD_ASM_ADJUST visium_md_asm_adjust
355 #undef TARGET_FLAGS_REGNUM
356 #define TARGET_FLAGS_REGNUM FLAGS_REGNUM
358 #undef TARGET_HARD_REGNO_NREGS
359 #define TARGET_HARD_REGNO_NREGS visium_hard_regno_nregs
361 #undef TARGET_HARD_REGNO_MODE_OK
362 #define TARGET_HARD_REGNO_MODE_OK visium_hard_regno_mode_ok
364 #undef TARGET_MODES_TIEABLE_P
365 #define TARGET_MODES_TIEABLE_P visium_modes_tieable_p
367 #undef TARGET_CAN_CHANGE_MODE_CLASS
368 #define TARGET_CAN_CHANGE_MODE_CLASS visium_can_change_mode_class
370 #undef TARGET_CONSTANT_ALIGNMENT
371 #define TARGET_CONSTANT_ALIGNMENT visium_constant_alignment
373 #undef TARGET_HAVE_SPECULATION_SAFE_VALUE
374 #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
376 struct gcc_target targetm
= TARGET_INITIALIZER
;
380 const pass_data pass_data_visium_reorg
=
384 OPTGROUP_NONE
, /* optinfo_flags */
385 TV_MACH_DEP
, /* tv_id */
386 0, /* properties_required */
387 0, /* properties_provided */
388 0, /* properties_destroyed */
389 0, /* todo_flags_start */
390 0, /* todo_flags_finish */
393 class pass_visium_reorg
: public rtl_opt_pass
396 pass_visium_reorg(gcc::context
*ctxt
)
397 : rtl_opt_pass(pass_data_visium_reorg
, ctxt
)
400 /* opt_pass methods: */
401 virtual unsigned int execute (function
*)
403 return visium_reorg ();
406 }; // class pass_work_around_errata
411 make_pass_visium_reorg (gcc::context
*ctxt
)
413 return new pass_visium_reorg (ctxt
);
416 /* Options override for Visium. */
419 visium_option_override (void)
422 warning (OPT_fpic
, "-fpic is not supported");
424 warning (OPT_fPIC
, "-fPIC is not supported");
426 /* MCM is the default in the GR5/GR6 era. */
427 target_flags
|= MASK_MCM
;
429 /* FPU is the default with MCM, but don't override an explicit option. */
430 if ((target_flags_explicit
& MASK_FPU
) == 0)
431 target_flags
|= MASK_FPU
;
433 /* The supervisor mode is the default. */
434 if ((target_flags_explicit
& MASK_SV_MODE
) == 0)
435 target_flags
|= MASK_SV_MODE
;
437 /* The GR6 has the Block Move Instructions and an IEEE-compliant FPU. */
438 if (visium_cpu_and_features
== PROCESSOR_GR6
)
440 target_flags
|= MASK_BMI
;
441 if (target_flags
& MASK_FPU
)
442 target_flags
|= MASK_FPU_IEEE
;
445 /* Set -mtune from -mcpu if not specified. */
446 if (!global_options_set
.x_visium_cpu
)
447 visium_cpu
= visium_cpu_and_features
;
449 /* Align functions on 256-byte (32-quadword) for GR5 and 64-byte (8-quadword)
450 boundaries for GR6 so they start a new burst mode window. */
451 if (flag_align_functions
&& !str_align_functions
)
453 if (visium_cpu
== PROCESSOR_GR6
)
454 str_align_functions
= "64";
456 str_align_functions
= "256";
458 /* Allow the size of compilation units to double because of inlining.
459 In practice the global size of the object code is hardly affected
460 because the additional instructions will take up the padding. */
461 maybe_set_param_value (PARAM_INLINE_UNIT_GROWTH
, 100,
462 global_options
.x_param_values
,
463 global_options_set
.x_param_values
);
466 /* Likewise for loops. */
467 if (flag_align_loops
&& !str_align_loops
)
469 if (visium_cpu
== PROCESSOR_GR6
)
470 str_align_loops
= "64";
473 /* But not if they are too far away from a 256-byte boundary. */
474 str_align_loops
= "256:32:8";
478 /* Align all jumps on quadword boundaries for the burst mode, and even
479 on 8-quadword boundaries for GR6 so they start a new window. */
480 if (flag_align_jumps
&& !str_align_jumps
)
482 if (visium_cpu
== PROCESSOR_GR6
)
483 str_align_jumps
= "64";
485 str_align_jumps
= "8";
488 /* We register a machine-specific pass. This pass must be scheduled as
489 late as possible so that we have the (essentially) final form of the
490 insn stream to work on. Registering the pass must be done at start up.
491 It's convenient to do it here. */
492 opt_pass
*visium_reorg_pass
= make_pass_visium_reorg (g
);
493 struct register_pass_info insert_pass_visium_reorg
=
495 visium_reorg_pass
, /* pass */
496 "dbr", /* reference_pass_name */
497 1, /* ref_pass_instance_number */
498 PASS_POS_INSERT_AFTER
/* po_op */
500 register_pass (&insert_pass_visium_reorg
);
503 /* Register the Visium-specific libfuncs with the middle-end. */
506 visium_init_libfuncs (void)
509 long_int_memcpy_libfunc
= init_one_libfunc ("__long_int_memcpy");
510 wrd_memcpy_libfunc
= init_one_libfunc ("__wrd_memcpy");
511 byt_memcpy_libfunc
= init_one_libfunc ("__byt_memcpy");
513 long_int_memset_libfunc
= init_one_libfunc ("__long_int_memset");
514 wrd_memset_libfunc
= init_one_libfunc ("__wrd_memset");
515 byt_memset_libfunc
= init_one_libfunc ("__byt_memset");
517 set_trampoline_parity_libfunc
= init_one_libfunc ("__set_trampoline_parity");
520 /* Return the number of instructions that can issue on the same cycle. */
523 visium_issue_rate (void)
538 /* Return the adjusted PRIORITY of INSN. */
541 visium_adjust_priority (rtx_insn
*insn
, int priority
)
543 /* On the GR5, we slightly increase the priority of writes in order to avoid
544 scheduling a read on the next cycle. This is necessary in addition to the
545 associated insn reservation because there are no data dependencies.
546 We also slightly increase the priority of reads from ROM in order to group
547 them as much as possible. These reads are a bit problematic because they
548 conflict with the instruction fetches, i.e. the data and instruction buses
549 tread on each other's toes when they are executed. */
550 if (visium_cpu
== PROCESSOR_GR5
553 && recog_memoized (insn
) >= 0)
555 enum attr_type attr_type
= get_attr_type (insn
);
556 if (attr_type
== TYPE_REG_MEM
557 || (attr_type
== TYPE_MEM_REG
558 && MEM_READONLY_P (SET_SRC (PATTERN (insn
)))))
565 /* Adjust the cost of a scheduling dependency. Return the new cost of
566 a dependency LINK of INSN on DEP_INSN. COST is the current cost. */
569 visium_adjust_cost (rtx_insn
*insn
, int dep_type
, rtx_insn
*dep_insn
, int cost
,
572 enum attr_type attr_type
;
574 /* Don't adjust costs for true dependencies as they are described with
575 bypasses. But we make an exception for the first scheduling pass to
576 help the subsequent postreload compare elimination pass. */
577 if (dep_type
== REG_DEP_TRUE
)
579 if (!reload_completed
580 && recog_memoized (insn
) >= 0
581 && get_attr_type (insn
) == TYPE_CMP
)
583 rtx pat
= PATTERN (insn
);
584 gcc_assert (GET_CODE (pat
) == SET
);
585 rtx src
= SET_SRC (pat
);
587 /* Only the branches can be modified by the postreload compare
588 elimination pass, not the cstores because they accept only
589 unsigned comparison operators and they are eliminated if
590 one of the operands is zero. */
591 if (GET_CODE (src
) == IF_THEN_ELSE
592 && XEXP (XEXP (src
, 0), 1) == const0_rtx
593 && recog_memoized (dep_insn
) >= 0)
595 enum attr_type dep_attr_type
= get_attr_type (dep_insn
);
597 /* The logical instructions use CCmode and thus work with any
598 comparison operator, whereas the arithmetic instructions use
599 CCNZmode and thus work with only a small subset. */
600 if (dep_attr_type
== TYPE_LOGIC
601 || (dep_attr_type
== TYPE_ARITH
602 && visium_nz_comparison_operator (XEXP (src
, 0),
612 if (recog_memoized (insn
) < 0)
615 attr_type
= get_attr_type (insn
);
617 /* Anti dependency: DEP_INSN reads a register that INSN writes some
619 if (dep_type
== REG_DEP_ANTI
)
621 /* On the GR5, the latency of FP instructions needs to be taken into
622 account for every dependency involving a write. */
623 if (attr_type
== TYPE_REG_FP
&& visium_cpu
== PROCESSOR_GR5
)
626 rtx pat
= PATTERN (insn
);
627 rtx dep_pat
= PATTERN (dep_insn
);
629 if (GET_CODE (pat
) != SET
|| GET_CODE (dep_pat
) != SET
)
630 /* If this happens, we have to extend this to schedule
631 optimally. Return 0 for now. */
634 if (reg_mentioned_p (SET_DEST (pat
), SET_SRC (dep_pat
)))
636 if (recog_memoized (dep_insn
) < 0)
639 switch (get_attr_type (dep_insn
))
647 /* A fload can't be issued until a preceding arithmetic
648 operation has finished if the target of the fload is
649 any of the sources (or destination) of the arithmetic
650 operation. Note that the latency may be (much)
651 greater than this if the preceding instruction
652 concerned is in a queue. */
653 return insn_default_latency (dep_insn
);
661 /* On the GR6, we try to make sure that the link register is restored
662 sufficiently ahead of the return as to yield a correct prediction
663 from the branch predictor. By default there is no true dependency
664 but an anti dependency between them, so we simply reuse it. */
665 else if (attr_type
== TYPE_RET
&& visium_cpu
== PROCESSOR_GR6
)
667 rtx dep_pat
= PATTERN (dep_insn
);
668 if (GET_CODE (dep_pat
) == SET
669 && REG_P (SET_DEST (dep_pat
))
670 && REGNO (SET_DEST (dep_pat
)) == LINK_REGNUM
)
674 /* For other anti dependencies, the cost is 0. */
678 /* Output dependency: DEP_INSN writes a register that INSN writes some
680 else if (dep_type
== REG_DEP_OUTPUT
)
682 /* On the GR5, the latency of FP instructions needs to be taken into
683 account for every dependency involving a write. */
684 if (attr_type
== TYPE_REG_FP
&& visium_cpu
== PROCESSOR_GR5
)
687 rtx pat
= PATTERN (insn
);
688 rtx dep_pat
= PATTERN (dep_insn
);
690 if (GET_CODE (pat
) != SET
|| GET_CODE (dep_pat
) != SET
)
691 /* If this happens, we have to extend this to schedule
692 optimally. Return 0 for now. */
695 if (reg_mentioned_p (SET_DEST (pat
), SET_DEST (dep_pat
)))
697 if (recog_memoized (dep_insn
) < 0)
700 switch (get_attr_type (dep_insn
))
708 /* A fload can't be issued until a preceding arithmetic
709 operation has finished if the target of the fload is
710 the destination of the arithmetic operation. Note that
711 the latency may be (much) greater than this if the
712 preceding instruction concerned is in a queue. */
713 return insn_default_latency (dep_insn
);
721 /* For other output dependencies, the cost is 0. */
728 /* Handle an "interrupt_handler" attribute; arguments as in
729 struct attribute_spec.handler. */
732 visium_handle_interrupt_attr (tree
*node
, tree name
,
733 tree args ATTRIBUTE_UNUSED
,
734 int flags ATTRIBUTE_UNUSED
,
737 if (TREE_CODE (*node
) != FUNCTION_DECL
)
739 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
741 *no_add_attrs
= true;
743 else if (!TARGET_SV_MODE
)
745 error ("an interrupt handler cannot be compiled with -muser-mode");
746 *no_add_attrs
= true;
752 /* Return non-zero if the current function is an interrupt function. */
755 visium_interrupt_function_p (void)
758 lookup_attribute ("interrupt",
759 DECL_ATTRIBUTES (current_function_decl
)) != NULL_TREE
;
762 /* Conditionally modify the settings of the register file. */
765 visium_conditional_register_usage (void)
767 /* If the supervisor mode is disabled, mask some general registers. */
770 if (visium_cpu_and_features
== PROCESSOR_GR5
)
772 fixed_regs
[24] = call_used_regs
[24] = 1;
773 fixed_regs
[25] = call_used_regs
[25] = 1;
774 fixed_regs
[26] = call_used_regs
[26] = 1;
775 fixed_regs
[27] = call_used_regs
[27] = 1;
776 fixed_regs
[28] = call_used_regs
[28] = 1;
777 call_really_used_regs
[24] = 0;
778 call_really_used_regs
[25] = 0;
779 call_really_used_regs
[26] = 0;
780 call_really_used_regs
[27] = 0;
781 call_really_used_regs
[28] = 0;
784 fixed_regs
[31] = call_used_regs
[31] = 1;
785 call_really_used_regs
[31] = 0;
787 /* We also need to change the long-branch register. */
788 if (visium_cpu_and_features
== PROCESSOR_GR5
)
789 long_branch_regnum
= 20;
791 long_branch_regnum
= 28;
794 /* If the FPU is disabled, mask the FP registers. */
797 for (int i
= FP_FIRST_REGNUM
; i
<= FP_LAST_REGNUM
; i
++)
799 fixed_regs
[i
] = call_used_regs
[i
] = 1;
800 call_really_used_regs
[i
] = 0;
805 /* Prepend to CLOBBERS hard registers that are automatically clobbered for
806 an asm We do this for the FLAGS to maintain source compatibility with
807 the original cc0-based compiler. */
810 visium_md_asm_adjust (vec
<rtx
> &/*outputs*/, vec
<rtx
> &/*inputs*/,
811 vec
<const char *> &/*constraints*/,
812 vec
<rtx
> &clobbers
, HARD_REG_SET
&clobbered_regs
)
814 clobbers
.safe_push (gen_rtx_REG (CCmode
, FLAGS_REGNUM
));
815 SET_HARD_REG_BIT (clobbered_regs
, FLAGS_REGNUM
);
819 /* Return true if X is a legitimate constant for a MODE immediate operand.
820 X is guaranteed to satisfy the CONSTANT_P predicate. */
823 visium_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED
,
824 rtx x ATTRIBUTE_UNUSED
)
829 /* Compute the alignment for a variable. The alignment of an aggregate is
830 set to be at least that of a scalar less than or equal to it in size. */
833 visium_data_alignment (tree type
, unsigned int align
)
835 if (AGGREGATE_TYPE_P (type
)
837 && TREE_CODE (TYPE_SIZE (type
)) == INTEGER_CST
&& align
< 32)
839 if (TREE_INT_CST_LOW (TYPE_SIZE (type
)) >= 32)
842 if (TREE_INT_CST_LOW (TYPE_SIZE (type
)) >= 16 && align
< 16)
849 /* Implement TARGET_CONSTANT_ALIGNMENT. */
852 visium_constant_alignment (const_tree exp
, HOST_WIDE_INT align
)
854 return visium_data_alignment (TREE_TYPE (exp
), align
);
857 /* Helper function for HARD_REGNO_RENAME_OK (FROM, TO). Return non-zero if
858 it is OK to rename a hard register FROM to another hard register TO. */
861 visium_hard_regno_rename_ok (unsigned int from ATTRIBUTE_UNUSED
,
864 /* If the function doesn't save LR, then the long-branch register will be
865 used for long branches so we need to know whether it is live before the
866 frame layout is computed. */
867 if (!current_function_saves_lr () && to
== long_branch_regnum
)
870 /* Interrupt functions can only use registers that have already been
871 saved by the prologue, even if they would normally be call-clobbered. */
873 && !df_regs_ever_live_p (to
)
874 && visium_interrupt_function_p ())
880 /* Implement TARGET_HARD_REGNO_NREGS. */
883 visium_hard_regno_nregs (unsigned int regno
, machine_mode mode
)
885 if (regno
== MDB_REGNUM
)
886 return CEIL (GET_MODE_SIZE (mode
), 2 * UNITS_PER_WORD
);
887 return CEIL (GET_MODE_SIZE (mode
), UNITS_PER_WORD
);
890 /* Implement TARGET_HARD_REGNO_MODE_OK.
892 Modes with sizes which cross from the one register class to the
893 other cannot be allowed. Only single floats are allowed in the
894 floating point registers, and only fixed point values in the EAM
898 visium_hard_regno_mode_ok (unsigned int regno
, machine_mode mode
)
900 if (GP_REGISTER_P (regno
))
901 return GP_REGISTER_P (end_hard_regno (mode
, regno
) - 1);
903 if (FP_REGISTER_P (regno
))
904 return mode
== SFmode
|| (mode
== SImode
&& TARGET_FPU_IEEE
);
906 return (GET_MODE_CLASS (mode
) == MODE_INT
907 && visium_hard_regno_nregs (regno
, mode
) == 1);
910 /* Implement TARGET_MODES_TIEABLE_P. */
913 visium_modes_tieable_p (machine_mode mode1
, machine_mode mode2
)
915 return (GET_MODE_CLASS (mode1
) == MODE_INT
916 && GET_MODE_CLASS (mode2
) == MODE_INT
);
919 /* Return true if it is ok to do sibling call optimization for the specified
920 call expression EXP. DECL will be the called function, or NULL if this
921 is an indirect call. */
924 visium_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED
,
925 tree exp ATTRIBUTE_UNUSED
)
927 return !visium_interrupt_function_p ();
930 /* Prepare operands for a move define_expand in MODE. */
933 prepare_move_operands (rtx
*operands
, machine_mode mode
)
935 /* If the output is not a register, the input must be. */
936 if (GET_CODE (operands
[0]) == MEM
&& !reg_or_0_operand (operands
[1], mode
))
937 operands
[1] = force_reg (mode
, operands
[1]);
940 /* Return true if the operands are valid for a simple move insn. */
943 ok_for_simple_move_operands (rtx
*operands
, machine_mode mode
)
945 /* One of the operands must be a register. */
946 if (!register_operand (operands
[0], mode
)
947 && !reg_or_0_operand (operands
[1], mode
))
950 /* Once the flags are exposed, no simple moves between integer registers. */
951 if (visium_flags_exposed
952 && gpc_reg_operand (operands
[0], mode
)
953 && gpc_reg_operand (operands
[1], mode
))
959 /* Return true if the operands are valid for a simple move strict insn. */
962 ok_for_simple_move_strict_operands (rtx
*operands
, machine_mode mode
)
964 /* Once the flags are exposed, no simple moves between integer registers.
965 Note that, in QImode only, a zero source counts as an integer register
966 since it will be emitted as r0. */
967 if (visium_flags_exposed
968 && gpc_reg_operand (operands
[0], mode
)
969 && (gpc_reg_operand (operands
[1], mode
)
970 || (mode
== QImode
&& operands
[1] == const0_rtx
)))
976 /* Return true if the operands are valid for a simple arithmetic or logical
980 ok_for_simple_arith_logic_operands (rtx
*, machine_mode
)
982 /* Once the flags are exposed, no simple arithmetic or logical operations
983 between integer registers. */
984 return !visium_flags_exposed
;
987 /* Return non-zero if a branch or call instruction will be emitting a nop
988 into its delay slot. */
991 empty_delay_slot (rtx_insn
*insn
)
995 /* If no previous instruction (should not happen), return true. */
996 if (PREV_INSN (insn
) == NULL
)
999 seq
= NEXT_INSN (PREV_INSN (insn
));
1000 if (GET_CODE (PATTERN (seq
)) == SEQUENCE
)
1006 /* Wrapper around single_set which returns the second SET of a pair if the
1007 first SET is to the flags register. */
1010 single_set_and_flags (rtx_insn
*insn
)
1012 if (multiple_sets (insn
))
1014 rtx pat
= PATTERN (insn
);
1015 if (XVECLEN (pat
, 0) == 2
1016 && GET_CODE (XVECEXP (pat
, 0, 0)) == SET
1017 && REG_P (SET_DEST (XVECEXP (pat
, 0, 0)))
1018 && REGNO (SET_DEST (XVECEXP (pat
, 0, 0))) == FLAGS_REGNUM
)
1019 return XVECEXP (pat
, 0, 1);
1022 return single_set (insn
);
1025 /* This is called with OUT_INSN an instruction setting a (base) register
1026 and IN_INSN a read or a write. Return 1 if these instructions together
1027 constitute a pipeline hazard.
1029 On the original architecture, a pipeline data hazard occurs when the Dest
1030 of one instruction becomes the SrcA for an immediately following READ or
1031 WRITE instruction with a non-zero index (indexing occurs at the decode
1032 stage and so a NOP must be inserted in-between for this to work).
1039 On the MCM, the non-zero index condition is lifted but the hazard is
1040 patched up by the hardware through the injection of wait states:
1045 We nevertheless try to schedule instructions around this. */
1048 gr5_hazard_bypass_p (rtx_insn
*out_insn
, rtx_insn
*in_insn
)
1050 rtx out_set
, in_set
, dest
, memexpr
;
1051 unsigned int out_reg
, in_reg
;
1053 /* A CALL is storage register class, but the link register is of no
1055 if (GET_CODE (out_insn
) == CALL_INSN
)
1058 out_set
= single_set_and_flags (out_insn
);
1059 dest
= SET_DEST (out_set
);
1061 /* Should be no stall/hazard if OUT_INSN is MEM := ???. This only
1062 occurs prior to reload. */
1063 if (GET_CODE (dest
) == MEM
)
1066 if (GET_CODE (dest
) == STRICT_LOW_PART
)
1067 dest
= XEXP (dest
, 0);
1068 if (GET_CODE (dest
) == SUBREG
)
1069 dest
= SUBREG_REG (dest
);
1070 out_reg
= REGNO (dest
);
1072 in_set
= single_set_and_flags (in_insn
);
1074 /* If IN_INSN is MEM := MEM, it's the source that counts. */
1075 if (GET_CODE (SET_SRC (in_set
)) == MEM
)
1076 memexpr
= XEXP (SET_SRC (in_set
), 0);
1078 memexpr
= XEXP (SET_DEST (in_set
), 0);
1080 if (GET_CODE (memexpr
) == PLUS
)
1082 memexpr
= XEXP (memexpr
, 0);
1083 if (GET_CODE (memexpr
) == SUBREG
)
1084 in_reg
= REGNO (SUBREG_REG (memexpr
));
1086 in_reg
= REGNO (memexpr
);
1088 if (in_reg
== out_reg
)
1091 else if (TARGET_MCM
)
1093 if (GET_CODE (memexpr
) == STRICT_LOW_PART
)
1094 memexpr
= XEXP (memexpr
, 0);
1095 if (GET_CODE (memexpr
) == SUBREG
)
1096 memexpr
= SUBREG_REG (memexpr
);
1097 in_reg
= REGNO (memexpr
);
1099 if (in_reg
== out_reg
)
1106 /* Return true if INSN is an empty asm instruction. */
1109 empty_asm_p (rtx insn
)
1111 rtx body
= PATTERN (insn
);
1114 if (GET_CODE (body
) == ASM_INPUT
)
1115 templ
= XSTR (body
, 0);
1116 else if (asm_noperands (body
) >= 0)
1117 templ
= decode_asm_operands (body
, NULL
, NULL
, NULL
, NULL
, NULL
);
1121 return (templ
&& templ
[0] == '\0');
1124 /* Insert a NOP immediately before INSN wherever there is a pipeline hazard.
1125 LAST_REG records the register set in the last insn and LAST_INSN_CALL
1126 records whether the last insn was a call insn. */
1129 gr5_avoid_hazard (rtx_insn
*insn
, unsigned int *last_reg
, bool *last_insn_call
)
1131 unsigned int dest_reg
= 0;
1134 switch (GET_CODE (insn
))
1138 *last_insn_call
= true;
1142 /* If this is an empty asm, just skip it. */
1143 if (!empty_asm_p (insn
))
1146 *last_insn_call
= false;
1151 /* If this is an empty asm, just skip it. */
1152 if (empty_asm_p (insn
))
1160 set
= single_set_and_flags (insn
);
1161 if (set
!= NULL_RTX
)
1163 rtx dest
= SET_DEST (set
);
1164 const bool double_p
= GET_MODE_SIZE (GET_MODE (dest
)) > UNITS_PER_WORD
;
1167 if (GET_CODE (SET_SRC (set
)) == MEM
)
1169 memrtx
= XEXP (SET_SRC (set
), 0);
1170 if (GET_CODE (dest
) == STRICT_LOW_PART
)
1171 dest
= XEXP (dest
, 0);
1173 dest_reg
= REGNO (dest
);
1175 /* If this is a DI or DF mode memory to register
1176 copy, then if rd = rs we get
1181 otherwise the order is
1188 unsigned int base_reg
;
1190 if (GET_CODE (memrtx
) == PLUS
)
1191 base_reg
= REGNO (XEXP (memrtx
, 0));
1193 base_reg
= REGNO (memrtx
);
1195 if (dest_reg
!= base_reg
)
1200 else if (GET_CODE (dest
) == MEM
)
1201 memrtx
= XEXP (dest
, 0);
1203 else if (GET_MODE_CLASS (GET_MODE (dest
)) != MODE_CC
)
1205 if (GET_CODE (dest
) == STRICT_LOW_PART
1206 ||GET_CODE (dest
) == ZERO_EXTRACT
)
1207 dest
= XEXP (dest
, 0);
1208 dest_reg
= REGNO (dest
);
1210 if (GET_CODE (SET_SRC (set
)) == REG
)
1212 unsigned int srcreg
= REGNO (SET_SRC (set
));
1214 /* Check for rs := rs, which will be deleted. */
1215 if (srcreg
== dest_reg
)
1218 /* In the case of a DI or DF mode move from register to
1219 register there is overlap if rd = rs + 1 in which case
1220 the order of the copies is reversed :
1225 if (double_p
&& dest_reg
!= srcreg
+ 1)
1230 /* If this is the delay slot of a call insn, any register it sets
1232 if (*last_insn_call
)
1235 /* If the previous insn sets the value of a register, and this insn
1236 uses a base register, check for the pipeline hazard where it is
1237 the same register in each case. */
1238 if (*last_reg
!= 0 && memrtx
!= NULL_RTX
)
1240 unsigned int reg
= 0;
1242 /* Check for an index (original architecture). */
1243 if (GET_CODE (memrtx
) == PLUS
)
1244 reg
= REGNO (XEXP (memrtx
, 0));
1246 /* Check for an MCM target or rs := [rs], in DI or DF mode. */
1247 else if (TARGET_MCM
|| (double_p
&& REGNO (memrtx
) == dest_reg
))
1248 reg
= REGNO (memrtx
);
1250 /* Remove any pipeline hazard by inserting a NOP. */
1251 if (reg
== *last_reg
)
1255 "inserting nop before insn %d\n", INSN_UID (insn
));
1256 emit_insn_after (gen_hazard_nop (), prev_active_insn (insn
));
1257 emit_insn_after (gen_blockage (), insn
);
1261 *last_reg
= dest_reg
;
1264 *last_insn_call
= false;
1267 /* Go through the instruction stream and insert nops where necessary to avoid
1268 pipeline hazards. There are two cases:
1270 1. On the original architecture, it is invalid to set the value of a
1271 (base) register and then use it in an address with a non-zero index
1272 in the next instruction.
1274 2. On the MCM, setting the value of a (base) register and then using
1275 it in address (including with zero index) in the next instruction
1276 will result in a pipeline stall of 3 cycles. */
1279 gr5_hazard_avoidance (void)
1281 unsigned int last_reg
= 0;
1282 bool last_insn_call
= false;
1285 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
1288 rtx pat
= PATTERN (insn
);
1290 if (GET_CODE (pat
) == SEQUENCE
)
1292 for (int i
= 0; i
< XVECLEN (pat
, 0); i
++)
1293 gr5_avoid_hazard (as_a
<rtx_insn
*> (XVECEXP (pat
, 0, i
)),
1294 &last_reg
, &last_insn_call
);
1297 else if (GET_CODE (insn
) == CALL_INSN
)
1299 /* This call is going to get a nop in its delay slot. */
1301 last_insn_call
= false;
1305 gr5_avoid_hazard (insn
, &last_reg
, &last_insn_call
);
1308 else if (GET_CODE (insn
) == BARRIER
)
1312 /* Perform a target-specific pass over the instruction stream. The compiler
1313 will run it at all optimization levels, just after the point at which it
1314 normally does delayed-branch scheduling. */
1319 if (visium_cpu
== PROCESSOR_GR5
)
1320 gr5_hazard_avoidance ();
1324 /* Return true if an argument must be passed by indirect reference. */
1327 visium_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED
,
1328 machine_mode mode ATTRIBUTE_UNUSED
,
1330 bool named ATTRIBUTE_UNUSED
)
1332 return type
&& (AGGREGATE_TYPE_P (type
) || TREE_CODE (type
) == VECTOR_TYPE
);
1335 /* Define how arguments are passed.
1337 A range of general registers and floating registers is available
1338 for passing arguments. When the class of registers which an
1339 argument would normally use is exhausted, that argument, is passed
1340 in the overflow region of the stack. No argument is split between
1341 registers and stack.
1343 Arguments of type float or _Complex float go in FP registers if FP
1344 hardware is available. If there is no FP hardware, arguments of
1345 type float go in general registers. All other arguments are passed
1346 in general registers. */
1349 visium_function_arg (cumulative_args_t pcum_v
, machine_mode mode
,
1350 const_tree type ATTRIBUTE_UNUSED
,
1351 bool named ATTRIBUTE_UNUSED
)
1354 CUMULATIVE_ARGS
*ca
= get_cumulative_args (pcum_v
);
1356 size
= (GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
1357 if (mode
== VOIDmode
)
1360 /* Scalar or complex single precision floating point arguments are returned
1361 in floating registers. */
1363 && ((GET_MODE_CLASS (mode
) == MODE_FLOAT
1364 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
)
1365 || (GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
1366 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
* 2)))
1368 if (ca
->frcount
+ size
<= MAX_ARGS_IN_FP_REGISTERS
)
1369 return gen_rtx_REG (mode
, FP_ARG_FIRST
+ ca
->frcount
);
1374 if (ca
->grcount
+ size
<= MAX_ARGS_IN_GP_REGISTERS
)
1375 return gen_rtx_REG (mode
, ca
->grcount
+ GP_ARG_FIRST
);
1380 /* Update the summarizer variable pointed to by PCUM_V to advance past an
1381 argument in the argument list. The values MODE, TYPE and NAMED describe
1382 that argument. Once this is done, the variable CUM is suitable for
1383 analyzing the _following_ argument with visium_function_arg. */
1386 visium_function_arg_advance (cumulative_args_t pcum_v
,
1388 const_tree type ATTRIBUTE_UNUSED
,
1391 int size
= (GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
1393 CUMULATIVE_ARGS
*ca
= get_cumulative_args (pcum_v
);
1395 /* Scalar or complex single precision floating point arguments are returned
1396 in floating registers. */
1398 && ((GET_MODE_CLASS (mode
) == MODE_FLOAT
1399 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
)
1400 || (GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
1401 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
* 2)))
1403 if (ca
->frcount
+ size
<= MAX_ARGS_IN_FP_REGISTERS
)
1404 ca
->frcount
+= size
;
1408 ca
->frcount
= MAX_ARGS_IN_FP_REGISTERS
;
1413 /* Everything else goes in a general register, if enough are
1415 if (ca
->grcount
+ size
<= MAX_ARGS_IN_GP_REGISTERS
)
1416 ca
->grcount
+= size
;
1420 ca
->grcount
= MAX_ARGS_IN_GP_REGISTERS
;
1425 ca
->stack_words
+= stack_size
;
1428 /* Specify whether to return the return value in memory. */
1431 visium_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
1433 return (AGGREGATE_TYPE_P (type
) || TREE_CODE (type
) == VECTOR_TYPE
);
1436 /* Define how scalar values are returned. */
1439 visium_function_value_1 (machine_mode mode
)
1441 /* Scalar or complex single precision floating point values
1442 are returned in floating register f1. */
1444 && ((GET_MODE_CLASS (mode
) == MODE_FLOAT
1445 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
)
1446 || (GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
1447 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
* 2)))
1448 return gen_rtx_REG (mode
, FP_RETURN_REGNUM
);
1450 /* All others are returned in r1. */
1451 return gen_rtx_REG (mode
, RETURN_REGNUM
);
1454 /* Return an RTX representing the place where a function returns or receives
1455 a value of data type RET_TYPE. */
1458 visium_function_value (const_tree ret_type
,
1459 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1460 bool outgoing ATTRIBUTE_UNUSED
)
1462 return visium_function_value_1 (TYPE_MODE (ret_type
));
1465 /* Return an RTX representing the place where the library function result will
1469 visium_libcall_value (machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
1471 return visium_function_value_1 (mode
);
1474 /* Store the anonymous register arguments into the stack so that all the
1475 arguments appear to have been passed consecutively on the stack. */
1478 visium_setup_incoming_varargs (cumulative_args_t pcum_v
,
1481 int *pretend_size ATTRIBUTE_UNUSED
,
1484 cumulative_args_t local_args_so_far
;
1485 CUMULATIVE_ARGS local_copy
;
1486 CUMULATIVE_ARGS
*locargs
;
1487 int gp_saved
, fp_saved
, size
;
1489 /* Create an internal cumulative_args_t pointer to internally define
1490 storage to ensure calling TARGET_FUNCTION_ARG_ADVANCE does not
1491 make global changes. */
1492 local_args_so_far
.p
= &local_copy
;
1493 locargs
= get_cumulative_args (pcum_v
);
1496 local_args_so_far
.magic
= CUMULATIVE_ARGS_MAGIC
;
1499 local_copy
.grcount
= locargs
->grcount
;
1500 local_copy
.frcount
= locargs
->frcount
;
1501 local_copy
.stack_words
= locargs
->stack_words
;
1503 /* The caller has advanced ARGS_SO_FAR up to, but not beyond, the last named
1504 argument. Advance a local copy of ARGS_SO_FAR past the last "real" named
1505 argument, to find out how many registers are left over. */
1506 TARGET_FUNCTION_ARG_ADVANCE (local_args_so_far
, mode
, type
, 1);
1508 /* Find how many registers we need to save. */
1509 locargs
= get_cumulative_args (local_args_so_far
);
1510 gp_saved
= MAX_ARGS_IN_GP_REGISTERS
- locargs
->grcount
;
1511 fp_saved
= (TARGET_FPU
? MAX_ARGS_IN_FP_REGISTERS
- locargs
->frcount
: 0);
1512 size
= (gp_saved
* UNITS_PER_WORD
) + (fp_saved
* UNITS_PER_HWFPVALUE
);
1514 if (!no_rtl
&& size
> 0)
1516 /* To avoid negative offsets, which are not valid addressing modes on
1517 the Visium, we create a base register for the pretend args. */
1520 plus_constant (Pmode
, virtual_incoming_args_rtx
, -size
));
1525 = gen_rtx_MEM (BLKmode
,
1526 plus_constant (Pmode
,
1528 fp_saved
* UNITS_PER_HWFPVALUE
));
1529 MEM_NOTRAP_P (mem
) = 1;
1530 set_mem_alias_set (mem
, get_varargs_alias_set ());
1531 move_block_from_reg (locargs
->grcount
+ GP_ARG_FIRST
, mem
, gp_saved
);
1536 rtx mem
= gen_rtx_MEM (BLKmode
, ptr
);
1537 MEM_NOTRAP_P (mem
) = 1;
1538 set_mem_alias_set (mem
, get_varargs_alias_set ());
1539 gcc_assert (UNITS_PER_WORD
== UNITS_PER_HWFPVALUE
);
1540 move_block_from_reg (locargs
->frcount
+ FP_ARG_FIRST
, mem
, fp_saved
);
1544 visium_reg_parm_save_area_size
= size
;
1547 /* Define the `__builtin_va_list' type for the ABI. */
1550 visium_build_builtin_va_list (void)
1552 tree f_ovfl
, f_gbase
, f_fbase
, f_gbytes
, f_fbytes
, record
;
1554 record
= (*lang_hooks
.types
.make_type
) (RECORD_TYPE
);
1555 f_ovfl
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1556 get_identifier ("__overflow_argptr"), ptr_type_node
);
1557 f_gbase
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1558 get_identifier ("__gpr_base"), ptr_type_node
);
1559 f_fbase
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1560 get_identifier ("__fpr_base"), ptr_type_node
);
1561 f_gbytes
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1562 get_identifier ("__gpr_bytes"),
1563 short_unsigned_type_node
);
1564 f_fbytes
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1565 get_identifier ("__fpr_bytes"),
1566 short_unsigned_type_node
);
1568 DECL_FIELD_CONTEXT (f_ovfl
) = record
;
1569 DECL_FIELD_CONTEXT (f_gbase
) = record
;
1570 DECL_FIELD_CONTEXT (f_fbase
) = record
;
1571 DECL_FIELD_CONTEXT (f_gbytes
) = record
;
1572 DECL_FIELD_CONTEXT (f_fbytes
) = record
;
1573 TYPE_FIELDS (record
) = f_ovfl
;
1574 TREE_CHAIN (f_ovfl
) = f_gbase
;
1575 TREE_CHAIN (f_gbase
) = f_fbase
;
1576 TREE_CHAIN (f_fbase
) = f_gbytes
;
1577 TREE_CHAIN (f_gbytes
) = f_fbytes
;
1578 layout_type (record
);
1583 /* Implement `va_start' for varargs and stdarg. */
1586 visium_va_start (tree valist
, rtx nextarg ATTRIBUTE_UNUSED
)
1588 const CUMULATIVE_ARGS
*ca
= &crtl
->args
.info
;
1589 int gp_saved
= MAX_ARGS_IN_GP_REGISTERS
- ca
->grcount
;
1590 int fp_saved
= (TARGET_FPU
? MAX_ARGS_IN_FP_REGISTERS
- ca
->frcount
: 0);
1591 int named_stack_size
= ca
->stack_words
* UNITS_PER_WORD
, offset
;
1592 tree f_ovfl
, f_gbase
, f_fbase
, f_gbytes
, f_fbytes
;
1593 tree ovfl
, gbase
, gbytes
, fbase
, fbytes
, t
;
1595 f_ovfl
= TYPE_FIELDS (va_list_type_node
);
1596 f_gbase
= TREE_CHAIN (f_ovfl
);
1597 f_fbase
= TREE_CHAIN (f_gbase
);
1598 f_gbytes
= TREE_CHAIN (f_fbase
);
1599 f_fbytes
= TREE_CHAIN (f_gbytes
);
1600 ovfl
= build3 (COMPONENT_REF
, TREE_TYPE (f_ovfl
), valist
, f_ovfl
, NULL_TREE
);
1601 gbase
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbase
), valist
, f_gbase
,
1603 fbase
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbase
), valist
, f_fbase
,
1605 gbytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbytes
), valist
, f_gbytes
,
1607 fbytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbytes
), valist
, f_fbytes
,
1610 /* Store the stacked vararg pointer in the OVFL member. */
1611 t
= make_tree (TREE_TYPE (ovfl
), virtual_incoming_args_rtx
);
1612 t
= fold_build_pointer_plus_hwi (t
, named_stack_size
);
1613 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ovfl
), ovfl
, t
);
1614 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1616 /* Store the base address of the GPR save area into GBASE. */
1617 t
= make_tree (TREE_TYPE (gbase
), virtual_incoming_args_rtx
);
1618 offset
= MAX_ARGS_IN_GP_REGISTERS
* UNITS_PER_WORD
;
1619 t
= fold_build_pointer_plus_hwi (t
, -offset
);
1620 t
= build2 (MODIFY_EXPR
, TREE_TYPE (gbase
), gbase
, t
);
1621 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1623 /* Store the base address of the FPR save area into FBASE. */
1626 t
= make_tree (TREE_TYPE (fbase
), virtual_incoming_args_rtx
);
1627 offset
= gp_saved
* UNITS_PER_WORD
1628 + MAX_ARGS_IN_FP_REGISTERS
* UNITS_PER_HWFPVALUE
;
1629 t
= fold_build_pointer_plus_hwi (t
, -offset
);
1630 t
= build2 (MODIFY_EXPR
, TREE_TYPE (fbase
), fbase
, t
);
1631 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1634 /* Fill in the GBYTES member. */
1635 t
= build2 (MODIFY_EXPR
, TREE_TYPE (gbytes
), gbytes
,
1636 size_int (gp_saved
* UNITS_PER_WORD
));
1637 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1639 /* Fill in the FBYTES member. */
1640 t
= build2 (MODIFY_EXPR
, TREE_TYPE (fbytes
),
1641 fbytes
, size_int (fp_saved
* UNITS_PER_HWFPVALUE
));
1642 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1645 /* Implement `va_arg'. */
1648 visium_gimplify_va_arg (tree valist
, tree type
, gimple_seq
*pre_p
,
1651 tree f_ovfl
, f_gbase
, f_fbase
, f_gbytes
, f_fbytes
;
1652 tree ovfl
, base
, bytes
;
1653 HOST_WIDE_INT size
, rsize
;
1654 const bool by_reference_p
1655 = pass_by_reference (NULL
, TYPE_MODE (type
), type
, false);
1656 const bool float_reg_arg_p
1657 = (TARGET_FPU
&& !by_reference_p
1658 && ((GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
1659 && GET_MODE_SIZE (TYPE_MODE (type
)) <= UNITS_PER_HWFPVALUE
)
1660 || (GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_COMPLEX_FLOAT
1661 && (GET_MODE_SIZE (TYPE_MODE (type
))
1662 <= UNITS_PER_HWFPVALUE
* 2))));
1663 const int max_save_area_size
1664 = (float_reg_arg_p
? MAX_ARGS_IN_FP_REGISTERS
* UNITS_PER_HWFPVALUE
1665 : MAX_ARGS_IN_GP_REGISTERS
* UNITS_PER_WORD
);
1667 tree lab_false
, lab_over
, addr
;
1668 tree ptrtype
= build_pointer_type (type
);
1672 t
= visium_gimplify_va_arg (valist
, ptrtype
, pre_p
, post_p
);
1673 return build_va_arg_indirect_ref (t
);
1676 size
= int_size_in_bytes (type
);
1677 rsize
= (size
+ UNITS_PER_WORD
- 1) & -UNITS_PER_WORD
;
1678 f_ovfl
= TYPE_FIELDS (va_list_type_node
);
1679 f_gbase
= TREE_CHAIN (f_ovfl
);
1680 f_fbase
= TREE_CHAIN (f_gbase
);
1681 f_gbytes
= TREE_CHAIN (f_fbase
);
1682 f_fbytes
= TREE_CHAIN (f_gbytes
);
1684 /* We maintain separate pointers and offsets for floating-point and
1685 general registers, but we need similar code in both cases.
1689 BYTES be the number of unused bytes in the register save area.
1690 BASE be the base address of the register save area.
1691 OFFS be the current offset into the register save area. Either
1692 MAX_ARGS_IN_GP_REGISTERS * UNITS_PER_WORD - bytes or
1693 MAX_ARGS_IN_FP_REGISTERS * UNITS_PER_HWFPVALUE - bytes
1694 depending upon whether the argument is in general or floating
1696 ADDR_RTX be the address of the argument.
1697 RSIZE be the size in bytes of the argument.
1698 OVFL be the pointer to the stack overflow area.
1700 The code we want is:
1702 1: if (bytes >= rsize)
1704 3: addr_rtx = base + offs;
1716 addr
= create_tmp_var (ptr_type_node
, "addr");
1717 lab_false
= create_artificial_label (UNKNOWN_LOCATION
);
1718 lab_over
= create_artificial_label (UNKNOWN_LOCATION
);
1719 if (float_reg_arg_p
)
1720 bytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbytes
), unshare_expr (valist
),
1721 f_fbytes
, NULL_TREE
);
1723 bytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbytes
), unshare_expr (valist
),
1724 f_gbytes
, NULL_TREE
);
1726 /* [1] Emit code to branch if bytes < rsize. */
1727 t
= fold_convert (TREE_TYPE (bytes
), size_int (rsize
));
1728 t
= build2 (LT_EXPR
, boolean_type_node
, bytes
, t
);
1729 u
= build1 (GOTO_EXPR
, void_type_node
, lab_false
);
1730 t
= build3 (COND_EXPR
, void_type_node
, t
, u
, NULL_TREE
);
1731 gimplify_and_add (t
, pre_p
);
1733 /* [3] Emit code for: addr_rtx = base + offs, where
1734 offs = max_save_area_size - bytes. */
1735 t
= fold_convert (sizetype
, bytes
);
1736 offs
= build2 (MINUS_EXPR
, sizetype
, size_int (max_save_area_size
), t
);
1737 if (float_reg_arg_p
)
1738 base
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbase
), valist
, f_fbase
,
1741 base
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbase
), valist
, f_gbase
,
1744 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (base
), base
, offs
);
1745 t
= build2 (MODIFY_EXPR
, void_type_node
, addr
, t
);
1746 gimplify_and_add (t
, pre_p
);
1748 /* [4] Emit code for: bytes -= rsize. */
1749 t
= fold_convert (TREE_TYPE (bytes
), size_int (rsize
));
1750 t
= build2 (MINUS_EXPR
, TREE_TYPE (bytes
), bytes
, t
);
1751 t
= build2 (MODIFY_EXPR
, TREE_TYPE (bytes
), bytes
, t
);
1752 gimplify_and_add (t
, pre_p
);
1754 /* [6] Emit code to branch over the else clause, then the label. */
1755 t
= build1 (GOTO_EXPR
, void_type_node
, lab_over
);
1756 gimplify_and_add (t
, pre_p
);
1757 t
= build1 (LABEL_EXPR
, void_type_node
, lab_false
);
1758 gimplify_and_add (t
, pre_p
);
1760 /* [8] Emit code for: bytes = 0. */
1761 t
= fold_convert (TREE_TYPE (bytes
), size_int (0));
1762 t
= build2 (MODIFY_EXPR
, TREE_TYPE (bytes
), unshare_expr (bytes
), t
);
1763 gimplify_and_add (t
, pre_p
);
1765 /* [9] Emit code for: addr_rtx = ovfl. */
1766 ovfl
= build3 (COMPONENT_REF
, TREE_TYPE (f_ovfl
), valist
, f_ovfl
, NULL_TREE
);
1767 t
= build2 (MODIFY_EXPR
, void_type_node
, addr
, ovfl
);
1768 gimplify_and_add (t
, pre_p
);
1770 /* [10] Emit code for: ovfl += rsize. */
1771 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (ovfl
), ovfl
, size_int (rsize
));
1772 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ovfl
), unshare_expr (ovfl
), t
);
1773 gimplify_and_add (t
, pre_p
);
1774 t
= build1 (LABEL_EXPR
, void_type_node
, lab_over
);
1775 gimplify_and_add (t
, pre_p
);
1777 /* Emit a big-endian correction if size < UNITS_PER_WORD. */
1778 if (size
< UNITS_PER_WORD
)
1780 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (addr
), addr
,
1781 size_int (UNITS_PER_WORD
- size
));
1782 t
= build2 (MODIFY_EXPR
, void_type_node
, addr
, t
);
1783 gimplify_and_add (t
, pre_p
);
1786 addr
= fold_convert (ptrtype
, addr
);
1788 return build_va_arg_indirect_ref (addr
);
1791 /* Return true if OP is an offset suitable for use as a displacement in the
1792 address of a memory access in mode MODE. */
1795 rtx_ok_for_offset_p (machine_mode mode
, rtx op
)
1797 if (!CONST_INT_P (op
) || INTVAL (op
) < 0)
1803 return INTVAL (op
) <= 31;
1806 return (INTVAL (op
) % 2) == 0 && INTVAL (op
) < 63;
1810 return (INTVAL (op
) % 4) == 0 && INTVAL (op
) < 127;
1814 return (INTVAL (op
) % 4) == 0 && INTVAL (op
) < 123;
1821 /* Return whether X is a legitimate memory address for a memory operand
1824 Legitimate addresses are defined in two variants: a strict variant
1825 and a non-strict one. The STRICT parameter chooses which variant
1826 is desired by the caller.
1828 The strict variant is used in the reload pass. It must be defined
1829 so that any pseudo-register that has not been allocated a hard
1830 register is considered a memory reference. This is because in
1831 contexts where some kind of register is required, a
1832 pseudo-register with no hard register must be rejected. For
1833 non-hard registers, the strict variant should look up the
1834 `reg_renumber' array; it should then proceed using the hard
1835 register number in the array, or treat the pseudo as a memory
1836 reference if the array holds `-1'.
1838 The non-strict variant is used in other passes. It must be
1839 defined to accept all pseudo-registers in every context where some
1840 kind of register is required. */
1843 visium_legitimate_address_p (machine_mode mode
, rtx x
, bool strict
)
1848 /* If X is base+disp, check that we have an appropriate offset. */
1849 if (GET_CODE (x
) == PLUS
)
1851 if (!rtx_ok_for_offset_p (mode
, XEXP (x
, 1)))
1858 /* Now check the base: it must be either a register or a subreg thereof. */
1859 if (GET_CODE (base
) == SUBREG
)
1860 base
= SUBREG_REG (base
);
1864 regno
= REGNO (base
);
1866 /* For the strict variant, the register must be REGNO_OK_FOR_BASE_P. */
1868 return REGNO_OK_FOR_BASE_P (regno
);
1870 /* For the non-strict variant, the register may also be a pseudo. */
1871 return BASE_REGISTER_P (regno
) || regno
>= FIRST_PSEUDO_REGISTER
;
1874 /* Try machine-dependent ways of modifying an illegitimate address
1875 to be legitimate. If we find one, return the new, valid address.
1876 This macro is used in only one place: `memory_address' in explow.c.
1878 OLDX is the address as it was before break_out_memory_refs was called.
1879 In some cases it is useful to look at this to decide what needs to be done.
1881 MODE and WIN are passed so that this macro can use
1882 GO_IF_LEGITIMATE_ADDRESS.
1884 It is always safe for this macro to do nothing. It exists to recognize
1885 opportunities to optimize the output.
1889 memory (reg + <out of range int>)
1893 base_int = <out of range int> & ~mask
1894 ptr_reg = reg + base_int
1895 memory (ptr_reg + <out of range int> - base_int)
1897 Thus ptr_reg is a base register for a range of addresses,
1898 which should help CSE.
1900 For a 1 byte reference mask is 0x1f
1901 for a 2 byte reference mask is 0x3f
1902 For a 4 byte reference mask is 0x7f
1904 This reflects the indexing range of the processor.
1906 For a > 4 byte reference the mask is 0x7f provided all of the words
1907 can be accessed with the base address obtained. Otherwise a mask
1910 On rare occasions an unaligned base register value with an
1911 unaligned offset is generated. Unaligned offsets are left alone for
1915 visium_legitimize_address (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
1918 if (GET_CODE (x
) == PLUS
1919 && GET_CODE (XEXP (x
, 1)) == CONST_INT
1920 && GET_CODE (XEXP (x
, 0)) == REG
&& mode
!= BLKmode
)
1922 int offset
= INTVAL (XEXP (x
, 1));
1923 int size
= GET_MODE_SIZE (mode
);
1924 int mask
= (size
== 1 ? 0x1f : (size
== 2 ? 0x3f : 0x7f));
1925 int mask1
= (size
== 1 ? 0 : (size
== 2 ? 1 : 3));
1926 int offset_base
= offset
& ~mask
;
1928 /* Check that all of the words can be accessed. */
1929 if (size
> 4 && size
+ offset
- offset_base
> 0x80)
1930 offset_base
= offset
& ~0x3f;
1931 if (offset_base
!= 0 && offset_base
!= offset
&& (offset
& mask1
) == 0)
1933 rtx ptr_reg
= force_reg (Pmode
,
1934 gen_rtx_PLUS (Pmode
,
1936 GEN_INT (offset_base
)));
1938 return plus_constant (Pmode
, ptr_reg
, offset
- offset_base
);
1945 /* Perform a similar function to visium_legitimize_address, but this time
1946 for reload. Generating new registers is not an option here. Parts
1947 that need reloading are indicated by calling push_reload. */
1950 visium_legitimize_reload_address (rtx x
, machine_mode mode
, int opnum
,
1951 int type
, int ind ATTRIBUTE_UNUSED
)
1953 rtx newrtx
, tem
= NULL_RTX
;
1955 if (mode
== BLKmode
)
1958 if (optimize
&& GET_CODE (x
) == PLUS
)
1959 tem
= simplify_binary_operation (PLUS
, GET_MODE (x
), XEXP (x
, 0),
1962 newrtx
= tem
? tem
: x
;
1963 if (GET_CODE (newrtx
) == PLUS
1964 && GET_CODE (XEXP (newrtx
, 1)) == CONST_INT
1965 && GET_CODE (XEXP (newrtx
, 0)) == REG
1966 && BASE_REGISTER_P (REGNO (XEXP (newrtx
, 0))))
1968 int offset
= INTVAL (XEXP (newrtx
, 1));
1969 int size
= GET_MODE_SIZE (mode
);
1970 int mask
= (size
== 1 ? 0x1f : (size
== 2 ? 0x3f : 0x7f));
1971 int mask1
= (size
== 1 ? 0 : (size
== 2 ? 1 : 3));
1972 int offset_base
= offset
& ~mask
;
1974 /* Check that all of the words can be accessed. */
1975 if (size
> 4 && size
+ offset
- offset_base
> 0x80)
1976 offset_base
= offset
& ~0x3f;
1978 if (offset_base
&& (offset
& mask1
) == 0)
1980 rtx temp
= gen_rtx_PLUS (Pmode
,
1981 XEXP (newrtx
, 0), GEN_INT (offset_base
));
1983 x
= gen_rtx_PLUS (Pmode
, temp
, GEN_INT (offset
- offset_base
));
1984 push_reload (XEXP (x
, 0), 0, &XEXP (x
, 0), 0,
1985 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
,
1986 (enum reload_type
) type
);
1994 /* Return the cost of moving data of mode MODE from a register in class FROM to
1995 one in class TO. A value of 2 is the default; other values are interpreted
1996 relative to that. */
1999 visium_register_move_cost (machine_mode mode
, reg_class_t from
,
2002 const int numwords
= (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
) ? 1 : 2;
2004 if (from
== MDB
|| to
== MDB
)
2006 else if (from
== MDC
|| to
== MDC
|| (from
== FP_REGS
) != (to
== FP_REGS
))
2007 return 4 * numwords
;
2009 return 2 * numwords
;
2012 /* Return the cost of moving data of mode MODE between a register of class
2013 CLASS and memory. IN is zero if the value is to be written to memory,
2014 non-zero if it is to be read in. This cost is relative to those in
2015 visium_register_move_cost. */
2018 visium_memory_move_cost (machine_mode mode
,
2019 reg_class_t to ATTRIBUTE_UNUSED
,
2022 /* Moving data in can be from PROM and this is expensive. */
2025 if (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
)
2031 /* Moving data out is mostly to RAM and should be cheaper. */
2034 if (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
)
2041 /* Return the relative costs of expression X. */
2044 visium_rtx_costs (rtx x
, machine_mode mode
, int outer_code ATTRIBUTE_UNUSED
,
2045 int opno ATTRIBUTE_UNUSED
, int *total
,
2046 bool speed ATTRIBUTE_UNUSED
)
2048 int code
= GET_CODE (x
);
2053 /* Small integers are as cheap as registers. 4-byte values can
2054 be fetched as immediate constants - let's give that the cost
2055 of an extra insn. */
2056 *total
= COSTS_N_INSNS (!satisfies_constraint_J (x
));
2062 *total
= COSTS_N_INSNS (2);
2068 split_double (x
, &high
, &low
);
2071 (!satisfies_constraint_J (high
) + !satisfies_constraint_J (low
));
2076 *total
= COSTS_N_INSNS (3);
2084 *total
= COSTS_N_INSNS (64);
2086 *total
= COSTS_N_INSNS (32);
2092 /* DImode operations are performed directly on the ALU. */
2094 *total
= COSTS_N_INSNS (2);
2096 *total
= COSTS_N_INSNS (1);
2102 /* DImode operations are performed on the EAM instead. */
2104 *total
= COSTS_N_INSNS (3);
2106 *total
= COSTS_N_INSNS (1);
2110 /* This matches the btst pattern. */
2111 if (GET_CODE (XEXP (x
, 0)) == ZERO_EXTRACT
2112 && XEXP (x
, 1) == const0_rtx
2113 && XEXP (XEXP (x
, 0), 1) == const1_rtx
2114 && satisfies_constraint_K (XEXP (XEXP (x
, 0), 2)))
2115 *total
= COSTS_N_INSNS (1);
2123 /* Split a double move of OPERANDS in MODE. */
2126 visium_split_double_move (rtx
*operands
, machine_mode mode
)
2130 /* Check register to register with overlap. */
2131 if (GET_CODE (operands
[0]) == REG
2132 && GET_CODE (operands
[1]) == REG
2133 && REGNO (operands
[0]) == REGNO (operands
[1]) + 1)
2136 /* Check memory to register where the base reg overlaps the destination. */
2137 if (GET_CODE (operands
[0]) == REG
&& GET_CODE (operands
[1]) == MEM
)
2139 rtx op
= XEXP (operands
[1], 0);
2141 if (GET_CODE (op
) == SUBREG
)
2142 op
= SUBREG_REG (op
);
2144 if (GET_CODE (op
) == REG
&& REGNO (op
) == REGNO (operands
[0]))
2147 if (GET_CODE (op
) == PLUS
)
2149 rtx x
= XEXP (op
, 0);
2150 rtx y
= XEXP (op
, 1);
2152 if (GET_CODE (x
) == REG
&& REGNO (x
) == REGNO (operands
[0]))
2155 if (GET_CODE (y
) == REG
&& REGNO (y
) == REGNO (operands
[0]))
2162 operands
[2] = operand_subword (operands
[0], 1, 1, mode
);
2163 operands
[3] = operand_subword (operands
[1], 1, 1, mode
);
2164 operands
[4] = operand_subword (operands
[0], 0, 1, mode
);
2165 operands
[5] = operand_subword (operands
[1], 0, 1, mode
);
2169 operands
[2] = operand_subword (operands
[0], 0, 1, mode
);
2170 operands
[3] = operand_subword (operands
[1], 0, 1, mode
);
2171 operands
[4] = operand_subword (operands
[0], 1, 1, mode
);
2172 operands
[5] = operand_subword (operands
[1], 1, 1, mode
);
2176 /* Split a double addition or subtraction of operands. */
2179 visium_split_double_add (enum rtx_code code
, rtx op0
, rtx op1
, rtx op2
)
2181 rtx op3
= gen_lowpart (SImode
, op0
);
2182 rtx op4
= gen_lowpart (SImode
, op1
);
2184 rtx op6
= gen_highpart (SImode
, op0
);
2185 rtx op7
= (op1
== const0_rtx
? op1
: gen_highpart (SImode
, op1
));
2189 /* If operand #2 is a small constant, then its high part is null. */
2190 if (CONST_INT_P (op2
))
2192 HOST_WIDE_INT val
= INTVAL (op2
);
2196 code
= (code
== MINUS
? PLUS
: MINUS
);
2200 op5
= gen_int_mode (val
, SImode
);
2205 op5
= gen_lowpart (SImode
, op2
);
2206 op8
= gen_highpart (SImode
, op2
);
2209 if (op4
== const0_rtx
)
2210 pat
= gen_negsi2_insn_set_carry (op3
, op5
);
2211 else if (code
== MINUS
)
2212 pat
= gen_subsi3_insn_set_carry (op3
, op4
, op5
);
2214 pat
= gen_addsi3_insn_set_carry (op3
, op4
, op5
);
2217 /* This is the plus_[plus_]sltu_flags or minus_[minus_]sltu_flags pattern. */
2218 if (op8
== const0_rtx
)
2221 x
= gen_rtx_fmt_ee (code
, SImode
, op7
, op8
);
2222 flags
= gen_rtx_REG (CCCmode
, FLAGS_REGNUM
);
2223 x
= gen_rtx_fmt_ee (code
, SImode
, x
, gen_rtx_LTU (SImode
, flags
, const0_rtx
));
2224 pat
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (2));
2225 XVECEXP (pat
, 0, 0) = gen_rtx_SET (op6
, x
);
2226 flags
= gen_rtx_REG (CCmode
, FLAGS_REGNUM
);
2227 XVECEXP (pat
, 0, 1) = gen_rtx_CLOBBER (VOIDmode
, flags
);
2230 visium_flags_exposed
= true;
2233 /* Expand a copysign of OPERANDS in MODE. */
2236 visium_expand_copysign (rtx
*operands
, machine_mode mode
)
2238 rtx op0
= operands
[0];
2239 rtx op1
= operands
[1];
2240 rtx op2
= operands
[2];
2241 rtx mask
= force_reg (SImode
, GEN_INT (0x7fffffff));
2244 /* We manually handle SFmode because the abs and neg instructions of
2245 the FPU on the MCM have a non-standard behavior wrt NaNs. */
2246 gcc_assert (mode
== SFmode
);
2248 /* First get all the non-sign bits of op1. */
2249 if (GET_CODE (op1
) == CONST_DOUBLE
)
2251 if (real_isneg (CONST_DOUBLE_REAL_VALUE (op1
)))
2252 op1
= simplify_unary_operation (ABS
, mode
, op1
, mode
);
2253 if (op1
!= CONST0_RTX (mode
))
2256 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op1
), l
);
2257 op1
= force_reg (SImode
, gen_int_mode (l
, SImode
));
2262 op1
= copy_to_mode_reg (SImode
, gen_lowpart (SImode
, op1
));
2263 op1
= force_reg (SImode
, gen_rtx_AND (SImode
, op1
, mask
));
2266 /* Then get the sign bit of op2. */
2267 mask
= force_reg (SImode
, gen_rtx_NOT (SImode
, mask
));
2268 op2
= copy_to_mode_reg (SImode
, gen_lowpart (SImode
, op2
));
2269 op2
= force_reg (SImode
, gen_rtx_AND (SImode
, op2
, mask
));
2271 /* Finally OR the two values. */
2272 if (op1
== CONST0_RTX (SFmode
))
2275 x
= force_reg (SImode
, gen_rtx_IOR (SImode
, op1
, op2
));
2277 /* And move the result to the destination. */
2278 emit_insn (gen_rtx_SET (op0
, gen_lowpart (SFmode
, x
)));
2281 /* Expand a cstore of OPERANDS in MODE for EQ/NE/LTU/GTU/GEU/LEU. We generate
2282 the result in the C flag and use the ADC/SUBC instructions to write it into
2283 the destination register.
2285 It would also be possible to implement support for LT/GT/LE/GE by means of
2286 the RFLAG instruction followed by some shifts, but this can pessimize the
2290 visium_expand_int_cstore (rtx
*operands
, machine_mode mode
)
2292 enum rtx_code code
= GET_CODE (operands
[1]);
2293 rtx op0
= operands
[0], op1
= operands
[2], op2
= operands
[3], sltu
;
2294 bool reverse
= false;
2300 /* We use a special comparison to get the result in the C flag. */
2301 if (op2
!= const0_rtx
)
2302 op1
= force_reg (mode
, gen_rtx_XOR (mode
, op1
, op2
));
2303 op1
= gen_rtx_NOT (mode
, op1
);
2311 /* The result is naturally in the C flag modulo a couple of tricks. */
2312 code
= reverse_condition (code
);
2315 /* ... fall through ... */
2331 /* We need either a single ADC or a SUBC and a PLUS. */
2332 sltu
= gen_rtx_LTU (SImode
, op1
, op2
);
2336 rtx tmp
= copy_to_mode_reg (SImode
, gen_rtx_NEG (SImode
, sltu
));
2337 emit_insn (gen_add3_insn (op0
, tmp
, const1_rtx
));
2340 emit_insn (gen_rtx_SET (op0
, sltu
));
2343 /* Expand a cstore of OPERANDS in MODE for LT/GT/UNGE/UNLE. We generate the
2344 result in the C flag and use the ADC/SUBC instructions to write it into
2345 the destination register. */
2348 visium_expand_fp_cstore (rtx
*operands
,
2349 machine_mode mode ATTRIBUTE_UNUSED
)
2351 enum rtx_code code
= GET_CODE (operands
[1]);
2352 rtx op0
= operands
[0], op1
= operands
[2], op2
= operands
[3], slt
;
2353 bool reverse
= false;
2359 /* The result is naturally in the C flag modulo a couple of tricks. */
2360 code
= reverse_condition_maybe_unordered (code
);
2363 /* ... fall through ... */
2379 /* We need either a single ADC or a SUBC and a PLUS. */
2380 slt
= gen_rtx_LT (SImode
, op1
, op2
);
2384 rtx tmp
= copy_to_mode_reg (SImode
, gen_rtx_NEG (SImode
, slt
));
2385 emit_insn (gen_add3_insn (op0
, tmp
, const1_rtx
));
2388 emit_insn (gen_rtx_SET (op0
, slt
));
2391 /* Split a compare-and-store with CODE, operands OP2 and OP3, combined with
2392 operation with OP_CODE, operands OP0 and OP1. */
2395 visium_split_cstore (enum rtx_code op_code
, rtx op0
, rtx op1
,
2396 enum rtx_code code
, rtx op2
, rtx op3
)
2398 machine_mode cc_mode
= visium_select_cc_mode (code
, op2
, op3
);
2400 /* If a FP cstore was reversed, then it was originally UNGE/UNLE. */
2401 if (cc_mode
== CCFPEmode
&& (op_code
== NEG
|| op_code
== MINUS
))
2404 rtx flags
= gen_rtx_REG (cc_mode
, FLAGS_REGNUM
);
2405 rtx x
= gen_rtx_COMPARE (cc_mode
, op2
, op3
);
2406 x
= gen_rtx_SET (flags
, x
);
2409 x
= gen_rtx_fmt_ee (code
, SImode
, flags
, const0_rtx
);
2415 x
= gen_rtx_NEG (SImode
, x
);
2419 x
= gen_rtx_fmt_ee (op_code
, SImode
, op1
, x
);
2425 rtx pat
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (2));
2426 XVECEXP (pat
, 0, 0) = gen_rtx_SET (op0
, x
);
2427 flags
= gen_rtx_REG (CCmode
, FLAGS_REGNUM
);
2428 XVECEXP (pat
, 0, 1) = gen_rtx_CLOBBER (VOIDmode
, flags
);
2431 visium_flags_exposed
= true;
2434 /* Generate a call to a library function to move BYTES_RTX bytes from SRC with
2435 address SRC_REG to DST with address DST_REG in 4-byte chunks. */
2438 expand_block_move_4 (rtx dst
, rtx dst_reg
, rtx src
, rtx src_reg
, rtx bytes_rtx
)
2440 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2441 unsigned int rem
= bytes
% 4;
2448 emit_move_insn (regno_reg_rtx
[1], dst_reg
);
2449 emit_move_insn (regno_reg_rtx
[2], src_reg
);
2450 emit_move_insn (regno_reg_rtx
[3], bytes_rtx
);
2452 insn
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (8));
2453 XVECEXP (insn
, 0, 0)
2454 = gen_rtx_SET (replace_equiv_address_nv (dst
, regno_reg_rtx
[1]),
2455 replace_equiv_address_nv (src
, regno_reg_rtx
[2]));
2456 XVECEXP (insn
, 0, 1) = gen_rtx_USE (VOIDmode
, regno_reg_rtx
[3]);
2457 for (i
= 1; i
<= 6; i
++)
2458 XVECEXP (insn
, 0, 1 + i
)
2459 = gen_rtx_CLOBBER (VOIDmode
, regno_reg_rtx
[i
]);
2463 emit_library_call (long_int_memcpy_libfunc
, LCT_NORMAL
, VOIDmode
,
2466 convert_to_mode (TYPE_MODE (sizetype
),
2467 GEN_INT (bytes
>> 2),
2468 TYPE_UNSIGNED (sizetype
)),
2469 TYPE_MODE (sizetype
));
2473 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2474 src
= replace_equiv_address_nv (src
, src_reg
);
2479 emit_move_insn (adjust_address_nv (dst
, HImode
, bytes
),
2480 adjust_address_nv (src
, HImode
, bytes
));
2486 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2487 adjust_address_nv (src
, QImode
, bytes
));
2490 /* Generate a call to a library function to move BYTES_RTX bytes from SRC with
2491 address SRC_REG to DST with address DST_REG in 2-bytes chunks. */
2494 expand_block_move_2 (rtx dst
, rtx dst_reg
, rtx src
, rtx src_reg
, rtx bytes_rtx
)
2496 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2497 unsigned int rem
= bytes
% 2;
2499 emit_library_call (wrd_memcpy_libfunc
, LCT_NORMAL
, VOIDmode
,
2502 convert_to_mode (TYPE_MODE (sizetype
),
2503 GEN_INT (bytes
>> 1),
2504 TYPE_UNSIGNED (sizetype
)),
2505 TYPE_MODE (sizetype
));
2509 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2510 src
= replace_equiv_address_nv (src
, src_reg
);
2513 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2514 adjust_address_nv (src
, QImode
, bytes
));
2517 /* Generate a call to a library function to move BYTES_RTX bytes from address
2518 SRC_REG to address DST_REG in 1-byte chunks. */
2521 expand_block_move_1 (rtx dst_reg
, rtx src_reg
, rtx bytes_rtx
)
2523 emit_library_call (byt_memcpy_libfunc
, LCT_NORMAL
, VOIDmode
,
2526 convert_to_mode (TYPE_MODE (sizetype
),
2528 TYPE_UNSIGNED (sizetype
)),
2529 TYPE_MODE (sizetype
));
2532 /* Generate a call to a library function to set BYTES_RTX bytes of DST with
2533 address DST_REG to VALUE_RTX in 4-byte chunks. */
2536 expand_block_set_4 (rtx dst
, rtx dst_reg
, rtx value_rtx
, rtx bytes_rtx
)
2538 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2539 unsigned int rem
= bytes
% 4;
2541 value_rtx
= convert_to_mode (Pmode
, value_rtx
, 1);
2542 emit_library_call (long_int_memset_libfunc
, LCT_NORMAL
, VOIDmode
,
2545 convert_to_mode (TYPE_MODE (sizetype
),
2546 GEN_INT (bytes
>> 2),
2547 TYPE_UNSIGNED (sizetype
)),
2548 TYPE_MODE (sizetype
));
2552 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2557 if (CONST_INT_P (value_rtx
))
2559 const unsigned HOST_WIDE_INT value
= UINTVAL (value_rtx
) & 0xff;
2560 emit_move_insn (adjust_address_nv (dst
, HImode
, bytes
),
2561 gen_int_mode ((value
<< 8) | value
, HImode
));
2565 rtx temp
= convert_to_mode (QImode
, value_rtx
, 1);
2566 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
), temp
);
2567 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
+ 1), temp
);
2574 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2575 convert_to_mode (QImode
, value_rtx
, 1));
2578 /* Generate a call to a library function to set BYTES_RTX bytes of DST with
2579 address DST_REG to VALUE_RTX in 2-byte chunks. */
2582 expand_block_set_2 (rtx dst
, rtx dst_reg
, rtx value_rtx
, rtx bytes_rtx
)
2584 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2585 unsigned int rem
= bytes
% 2;
2587 value_rtx
= convert_to_mode (Pmode
, value_rtx
, 1);
2588 emit_library_call (wrd_memset_libfunc
, LCT_NORMAL
, VOIDmode
,
2591 convert_to_mode (TYPE_MODE (sizetype
),
2592 GEN_INT (bytes
>> 1),
2593 TYPE_UNSIGNED (sizetype
)),
2594 TYPE_MODE (sizetype
));
2598 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2601 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2602 convert_to_mode (QImode
, value_rtx
, 1));
2605 /* Generate a call to a library function to set BYTES_RTX bytes at address
2606 DST_REG to VALUE_RTX in 1-byte chunks. */
2609 expand_block_set_1 (rtx dst_reg
, rtx value_rtx
, rtx bytes_rtx
)
2611 value_rtx
= convert_to_mode (Pmode
, value_rtx
, 1);
2612 emit_library_call (byt_memset_libfunc
, LCT_NORMAL
, VOIDmode
,
2615 convert_to_mode (TYPE_MODE (sizetype
),
2617 TYPE_UNSIGNED (sizetype
)),
2618 TYPE_MODE (sizetype
));
2621 /* Expand string/block move operations.
2623 operands[0] is the pointer to the destination.
2624 operands[1] is the pointer to the source.
2625 operands[2] is the number of bytes to move.
2626 operands[3] is the alignment.
2628 Return 1 upon success, 0 otherwise. */
2631 visium_expand_block_move (rtx
*operands
)
2633 rtx dst
= operands
[0];
2634 rtx src
= operands
[1];
2635 rtx bytes_rtx
= operands
[2];
2636 rtx align_rtx
= operands
[3];
2637 const int align
= INTVAL (align_rtx
);
2638 rtx dst_reg
, src_reg
;
2639 tree dst_expr
, src_expr
;
2641 /* We only handle a fixed number of bytes for now. */
2642 if (!CONST_INT_P (bytes_rtx
) || INTVAL (bytes_rtx
) <= 0)
2645 /* Copy the addresses into scratch registers. */
2646 dst_reg
= copy_addr_to_reg (XEXP (dst
, 0));
2647 src_reg
= copy_addr_to_reg (XEXP (src
, 0));
2649 /* Move the data with the appropriate granularity. */
2651 expand_block_move_4 (dst
, dst_reg
, src
, src_reg
, bytes_rtx
);
2652 else if (align
>= 2)
2653 expand_block_move_2 (dst
, dst_reg
, src
, src_reg
, bytes_rtx
);
2655 expand_block_move_1 (dst_reg
, src_reg
, bytes_rtx
);
2657 /* Since DST and SRC are passed to a libcall, mark the corresponding
2658 tree EXPR as addressable. */
2659 dst_expr
= MEM_EXPR (dst
);
2660 src_expr
= MEM_EXPR (src
);
2662 mark_addressable (dst_expr
);
2664 mark_addressable (src_expr
);
2669 /* Expand string/block set operations.
2671 operands[0] is the pointer to the destination.
2672 operands[1] is the number of bytes to set.
2673 operands[2] is the source value.
2674 operands[3] is the alignment.
2676 Return 1 upon success, 0 otherwise. */
2679 visium_expand_block_set (rtx
*operands
)
2681 rtx dst
= operands
[0];
2682 rtx bytes_rtx
= operands
[1];
2683 rtx value_rtx
= operands
[2];
2684 rtx align_rtx
= operands
[3];
2685 const int align
= INTVAL (align_rtx
);
2689 /* We only handle a fixed number of bytes for now. */
2690 if (!CONST_INT_P (bytes_rtx
) || INTVAL (bytes_rtx
) <= 0)
2693 /* Copy the address into a scratch register. */
2694 dst_reg
= copy_addr_to_reg (XEXP (dst
, 0));
2696 /* Set the data with the appropriate granularity. */
2698 expand_block_set_4 (dst
, dst_reg
, value_rtx
, bytes_rtx
);
2699 else if (align
>= 2)
2700 expand_block_set_2 (dst
, dst_reg
, value_rtx
, bytes_rtx
);
2702 expand_block_set_1 (dst_reg
, value_rtx
, bytes_rtx
);
2704 /* Since DST is passed to a libcall, mark the corresponding
2705 tree EXPR as addressable. */
2706 dst_expr
= MEM_EXPR (dst
);
2708 mark_addressable (dst_expr
);
2713 /* Initialize a trampoline. M_TRAMP is an RTX for the memory block for the
2714 trampoline, FNDECL is the FUNCTION_DECL for the nested function and
2715 STATIC_CHAIN is an RTX for the static chain value that should be passed
2716 to the function when it is called. */
2719 visium_trampoline_init (rtx m_tramp
, tree fndecl
, rtx static_chain
)
2721 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2722 rtx addr
= XEXP (m_tramp
, 0);
2724 /* The trampoline initialization sequence is:
2726 moviu r9,%u FUNCTION
2727 movil r9,%l FUNCTION
2732 We don't use r0 as the destination register of the branch because we want
2733 the Branch Pre-decode Logic of the GR6 to use the Address Load Array to
2734 predict the branch target. */
2736 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 0)),
2737 plus_constant (SImode
,
2738 expand_shift (RSHIFT_EXPR
, SImode
, fnaddr
,
2742 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 4)),
2743 plus_constant (SImode
,
2744 expand_and (SImode
, fnaddr
, GEN_INT (0xffff),
2748 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 8)),
2749 plus_constant (SImode
,
2750 expand_shift (RSHIFT_EXPR
, SImode
,
2755 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 12)),
2756 gen_int_mode (0xff892404, SImode
));
2758 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 16)),
2759 plus_constant (SImode
,
2760 expand_and (SImode
, static_chain
,
2761 GEN_INT (0xffff), NULL_RTX
),
2764 emit_library_call (set_trampoline_parity_libfunc
, LCT_NORMAL
, VOIDmode
,
2768 /* Return true if the current function must have and use a frame pointer. */
2771 visium_frame_pointer_required (void)
2773 /* The frame pointer is required if the function isn't leaf to be able to
2774 do manual stack unwinding. */
2778 /* If the stack pointer is dynamically modified in the function, it cannot
2779 serve as the frame pointer. */
2780 if (!crtl
->sp_is_unchanging
)
2783 /* If the function receives nonlocal gotos, it needs to save the frame
2784 pointer in the nonlocal_goto_save_area object. */
2785 if (cfun
->has_nonlocal_label
)
2788 /* The frame also needs to be established in some special cases. */
2789 if (visium_frame_needed
)
2795 /* Profiling support. Just a call to MCOUNT is needed. No labelled counter
2796 location is involved. Proper support for __builtin_return_address is also
2797 required, which is fairly straightforward provided a frame gets created. */
2800 visium_profile_hook (void)
2802 visium_frame_needed
= true;
2803 emit_library_call (gen_rtx_SYMBOL_REF (Pmode
, "mcount"), LCT_NORMAL
,
2807 /* A C expression whose value is RTL representing the address in a stack frame
2808 where the pointer to the caller's frame is stored. Assume that FRAMEADDR is
2809 an RTL expression for the address of the stack frame itself.
2811 If you don't define this macro, the default is to return the value of
2812 FRAMEADDR--that is, the stack frame address is also the address of the stack
2813 word that points to the previous frame. */
2816 visium_dynamic_chain_address (rtx frame
)
2818 /* This is the default, but we need to make sure the frame gets created. */
2819 visium_frame_needed
= true;
2823 /* A C expression whose value is RTL representing the value of the return
2824 address for the frame COUNT steps up from the current frame, after the
2825 prologue. FRAMEADDR is the frame pointer of the COUNT frame, or the frame
2826 pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' is
2829 The value of the expression must always be the correct address when COUNT is
2830 zero, but may be `NULL_RTX' if there is not way to determine the return
2831 address of other frames. */
2834 visium_return_addr_rtx (int count
, rtx frame ATTRIBUTE_UNUSED
)
2836 /* Dont try to compute anything other than frame zero. */
2840 visium_frame_needed
= true;
2842 gen_frame_mem (Pmode
, plus_constant (Pmode
, hard_frame_pointer_rtx
, 4));
2845 /* Helper function for EH_RETURN_HANDLER_RTX. Return the RTX representing a
2846 location in which to store the address of an exception handler to which we
2850 visium_eh_return_handler_rtx (void)
2853 = gen_frame_mem (SImode
, plus_constant (Pmode
, hard_frame_pointer_rtx
, 4));
2854 MEM_VOLATILE_P (mem
) = 1;
2858 static struct machine_function
*
2859 visium_init_machine_status (void)
2861 return ggc_cleared_alloc
<machine_function
> ();
2864 /* The per-function data machinery is needed to indicate when a frame
2868 visium_init_expanders (void)
2870 init_machine_status
= visium_init_machine_status
;
2873 /* Given a comparison code (EQ, NE, etc.) and the operands of a COMPARE,
2874 return the mode to be used for the comparison. */
2877 visium_select_cc_mode (enum rtx_code code
, rtx op0
, rtx op1
)
2879 if (GET_MODE_CLASS (GET_MODE (op0
)) == MODE_FLOAT
)
2899 /* These 2 comparison codes are not supported. */
2907 /* This is for the cmp<mode>_sne pattern. */
2908 if (op1
== constm1_rtx
)
2911 /* This is for the add<mode>3_insn_set_carry pattern. */
2912 if ((code
== LTU
|| code
== GEU
)
2913 && GET_CODE (op0
) == PLUS
2914 && rtx_equal_p (XEXP (op0
, 0), op1
))
2917 /* This is for the {add,sub,neg}<mode>3_insn_set_overflow pattern. */
2918 if ((code
== EQ
|| code
== NE
)
2919 && GET_CODE (op1
) == UNSPEC
2920 && (XINT (op1
, 1) == UNSPEC_ADDV
2921 || XINT (op1
, 1) == UNSPEC_SUBV
2922 || XINT (op1
, 1) == UNSPEC_NEGV
))
2925 if (op1
!= const0_rtx
)
2928 switch (GET_CODE (op0
))
2936 /* The C and V flags may be set differently from a COMPARE with zero.
2937 The consequence is that a comparison operator testing C or V must
2938 be turned into another operator not testing C or V and yielding
2939 the same result for a comparison with zero. That's possible for
2940 GE/LT which become NC/NS respectively, but not for GT/LE for which
2941 the altered operator doesn't exist on the Visium. */
2945 /* This is a btst, the result is in C instead of Z. */
2957 /* Pretend that the flags are set as for a COMPARE with zero.
2958 That's mostly true, except for the 2 right shift insns that
2959 will set the C flag. But the C flag is relevant only for
2960 the unsigned comparison operators and they are eliminated
2961 when applied to a comparison with zero. */
2964 /* ??? Cater to the junk RTXes sent by try_merge_compare. */
2980 /* Split a compare-and-branch with CODE, operands OP0 and OP1, and LABEL. */
2983 visium_split_cbranch (enum rtx_code code
, rtx op0
, rtx op1
, rtx label
)
2985 machine_mode cc_mode
= visium_select_cc_mode (code
, op0
, op1
);
2986 rtx flags
= gen_rtx_REG (cc_mode
, FLAGS_REGNUM
);
2988 rtx x
= gen_rtx_COMPARE (cc_mode
, op0
, op1
);
2989 x
= gen_rtx_SET (flags
, x
);
2992 x
= gen_rtx_fmt_ee (code
, VOIDmode
, flags
, const0_rtx
);
2993 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
, gen_rtx_LABEL_REF (Pmode
, label
),
2995 x
= gen_rtx_SET (pc_rtx
, x
);
2998 visium_flags_exposed
= true;
3001 /* Branch instructions on the Visium.
3003 Setting aside the interrupt-handling specific instructions, the ISA has
3004 two branch instructions: BRR and BRA. The former is used to implement
3005 short branches (+/- 2^17) within functions and its target is encoded in
3006 the instruction. The latter is used to implement all the other types
3007 of control flow changes and its target might not be statically known
3008 or even easily predictable at run time. Here's a complete summary of
3009 the patterns that generate a BRA instruction:
3019 Among these patterns, only the return (5) and the long branch (6) can be
3020 conditional; all the other patterns are always unconditional.
3022 The following algorithm can be used to identify the pattern for which
3023 the BRA instruction was generated and work out its target:
3025 A. If the source is r21 and the destination is r0, this is a return (5)
3026 and the target is the caller (i.e. the value of r21 on function's
3029 B. If the source is rN, N != 21 and the destination is r0, this is either
3030 an indirect jump or a table jump (1, 2) and the target is not easily
3033 C. If the source is rN, N != 21 and the destination is r21, this is a call
3034 (3) and the target is given by the preceding MOVIL/MOVIU pair for rN,
3035 unless this is an indirect call in which case the target is not easily
3038 D. If the source is rN, N != 21 and the destination is also rN, this is
3039 either a sibling call or a trampoline (4, 7) and the target is given
3040 by the preceding MOVIL/MOVIU pair for rN.
3042 E. If the source is r21 and the destination is also r21, this is a long
3043 branch (6) and the target is given by the preceding MOVIL/MOVIU pair
3046 The other combinations are not used. This implementation has been devised
3047 to accommodate the branch predictor of the GR6 but is used unconditionally
3048 by the compiler, i.e. including for earlier processors. */
3050 /* Output a conditional/unconditional branch to LABEL. COND is the string
3051 condition. INSN is the instruction. */
3054 output_branch (rtx label
, const char *cond
, rtx_insn
*insn
)
3060 operands
[0] = label
;
3062 /* If the length of the instruction is greater than 8, then this is a
3063 long branch and we need to work harder to emit it properly. */
3064 if (get_attr_length (insn
) > 8)
3068 /* If the link register has been saved, then we use it. */
3069 if (current_function_saves_lr ())
3071 operands
[1] = regno_reg_rtx
[LINK_REGNUM
];
3075 /* Or else, if the long-branch register isn't live, we use it. */
3076 else if (!df_regs_ever_live_p (long_branch_regnum
))
3078 operands
[1] = regno_reg_rtx
[long_branch_regnum
];
3082 /* Otherwise, we will use the long-branch register but we need to
3083 spill it to the stack and reload it at the end. We should have
3084 reserved the LR slot for this purpose. */
3087 operands
[1] = regno_reg_rtx
[long_branch_regnum
];
3089 gcc_assert (current_function_has_lr_slot ());
3092 /* First emit the spill to the stack:
3095 write.l [1](sp),reg */
3100 rtx_insn
*delay
= NEXT_INSN (insn
);
3103 final_scan_insn (delay
, asm_out_file
, optimize
, 0, NULL
);
3104 PATTERN (delay
) = gen_blockage ();
3105 INSN_CODE (delay
) = -1;
3108 if (current_function_saves_fp ())
3109 output_asm_insn ("write.l 1(sp),%1", operands
);
3111 output_asm_insn ("write.l (sp),%1", operands
);
3114 /* Then emit the core sequence:
3120 We don't use r0 as the destination register of the branch because we
3121 want the Branch Pre-decode Logic of the GR6 to use the Address Load
3122 Array to predict the branch target. */
3123 output_asm_insn ("moviu %1,%%u %0", operands
);
3124 output_asm_insn ("movil %1,%%l %0", operands
);
3125 strcpy (str
, "bra ");
3127 strcat (str
, ",%1,%1");
3130 strcat (str
, "\t\t;long branch");
3131 output_asm_insn (str
, operands
);
3133 /* Finally emit the reload:
3135 read.l reg,[1](sp) */
3138 if (current_function_saves_fp ())
3139 output_asm_insn (" read.l %1,1(sp)", operands
);
3141 output_asm_insn (" read.l %1,(sp)", operands
);
3145 /* Or else, if the label is PC, then this is a return. */
3146 else if (label
== pc_rtx
)
3148 strcpy (str
, "bra ");
3150 strcat (str
, ",r21,r0%#\t\t;return");
3151 output_asm_insn (str
, operands
);
3154 /* Otherwise, this is a short branch. */
3157 strcpy (str
, "brr ");
3159 strcat (str
, ",%0%#");
3160 output_asm_insn (str
, operands
);
3166 /* Output an unconditional branch to LABEL. INSN is the instruction. */
3169 output_ubranch (rtx label
, rtx_insn
*insn
)
3171 return output_branch (label
, "tr", insn
);
3174 /* Output a conditional branch to LABEL. CODE is the comparison code.
3175 CC_MODE is the mode of the CC register. REVERSED is non-zero if we
3176 should reverse the sense of the comparison. INSN is the instruction. */
3179 output_cbranch (rtx label
, enum rtx_code code
, machine_mode cc_mode
,
3180 int reversed
, rtx_insn
*insn
)
3186 if (cc_mode
== CCFPmode
|| cc_mode
== CCFPEmode
)
3187 code
= reverse_condition_maybe_unordered (code
);
3189 code
= reverse_condition (code
);
3195 if (cc_mode
== CCCmode
)
3197 else if (cc_mode
== CCVmode
)
3204 if (cc_mode
== CCCmode
)
3206 else if (cc_mode
== CCVmode
)
3213 if (cc_mode
== CCNZmode
)
3224 if (cc_mode
== CCFPmode
|| cc_mode
== CCFPEmode
)
3231 if (cc_mode
== CCFPmode
|| cc_mode
== CCFPEmode
)
3232 cond
= "cs"; /* or "ns" */
3233 else if (cc_mode
== CCNZmode
)
3264 cond
= "cc"; /* or "nc" */
3279 /* These 2 comparison codes are not supported. */
3286 return output_branch (label
, cond
, insn
);
3289 /* Implement TARGET_PRINT_OPERAND_PUNCT_VALID_P. */
3292 visium_print_operand_punct_valid_p (unsigned char code
)
3297 /* Implement TARGET_PRINT_OPERAND. Output to stdio stream FILE the assembler
3298 syntax for an instruction operand OP subject to the modifier LETTER. */
3301 visium_print_operand (FILE *file
, rtx op
, int letter
)
3306 /* Output an insn in a delay slot. */
3308 visium_indent_opcode
= 1;
3310 fputs ("\n\t nop", file
);
3314 /* Print LS 8 bits of operand. */
3315 fprintf (file
, HOST_WIDE_INT_PRINT_UNSIGNED
, UINTVAL (op
) & 0xff);
3319 /* Print LS 16 bits of operand. */
3320 fprintf (file
, HOST_WIDE_INT_PRINT_UNSIGNED
, UINTVAL (op
) & 0xffff);
3324 /* Print MS 16 bits of operand. */
3326 HOST_WIDE_INT_PRINT_UNSIGNED
, (UINTVAL (op
) >> 16) & 0xffff);
3330 /* It's either a register or zero. */
3331 if (GET_CODE (op
) == REG
)
3332 fputs (reg_names
[REGNO (op
)], file
);
3334 fputs (reg_names
[0], file
);
3338 /* It's either a FP register or zero. */
3339 if (GET_CODE (op
) == REG
)
3340 fputs (reg_names
[REGNO (op
)], file
);
3342 fputs (reg_names
[FP_FIRST_REGNUM
], file
);
3346 switch (GET_CODE (op
))
3350 fputs (reg_names
[REGNO (op
) + 1], file
);
3352 fputs (reg_names
[REGNO (op
)], file
);
3358 output_addr_const (file
, op
);
3362 visium_print_operand_address (file
, GET_MODE (op
), XEXP (op
, 0));
3366 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (op
));
3370 asm_fprintf (file
, "%LL%d", CODE_LABEL_NUMBER (op
));
3374 visium_print_operand (file
, XEXP (op
, 1), letter
);
3378 fatal_insn ("illegal operand ", op
);
3382 /* Implement TARGET_PRINT_OPERAND_ADDRESS. Output to stdio stream FILE the
3383 assembler syntax for an instruction operand that is a memory reference
3384 whose address is ADDR. */
3387 visium_print_operand_address (FILE *file
, machine_mode mode
, rtx addr
)
3389 switch (GET_CODE (addr
))
3393 fprintf (file
, "(%s)", reg_names
[true_regnum (addr
)]);
3398 rtx x
= XEXP (addr
, 0), y
= XEXP (addr
, 1);
3400 switch (GET_CODE (x
))
3404 if (CONST_INT_P (y
))
3406 unsigned int regno
= true_regnum (x
);
3407 HOST_WIDE_INT val
= INTVAL (y
);
3425 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
"(%s)", val
,
3429 fatal_insn ("illegal operand address (1)", addr
);
3433 if (CONSTANT_P (x
) && CONSTANT_P (y
))
3434 output_addr_const (file
, addr
);
3436 fatal_insn ("illegal operand address (2)", addr
);
3446 output_addr_const (file
, addr
);
3450 if (NOTE_KIND (addr
) != NOTE_INSN_DELETED_LABEL
)
3451 fatal_insn ("illegal operand address (3)", addr
);
3455 asm_fprintf (file
, "%LL%d", CODE_LABEL_NUMBER (addr
));
3459 fatal_insn ("illegal operand address (4)", addr
);
3464 /* The Visium stack frames look like:
3466 Before call After call
3467 +-----------------------+ +-----------------------+
3469 high | previous | | previous |
3470 mem | frame | | frame |
3472 +-----------------------+ +-----------------------+
3474 | arguments on stack | | arguments on stack |
3476 SP+0->+-----------------------+ +-----------------------+
3477 | reg parm save area, |
3478 | only created for |
3479 | variable argument |
3481 +-----------------------+
3483 | register save area |
3485 +-----------------------+
3489 FP+8->+-----------------------+
3491 FP+4->+-----------------------+
3493 FP+0->+-----------------------+
3495 | alloca allocations |
3497 +-----------------------+
3499 low | arguments on stack |
3501 SP+0->+-----------------------+
3504 1) The "reg parm save area" does not exist for non variable argument fns.
3505 2) The FP register is not saved if `frame_pointer_needed' is zero and it
3506 is not altered in the current function.
3507 3) The return address is not saved if there is no frame pointer and the
3508 current function is leaf.
3509 4) If the return address is not saved and the static chain register is
3510 live in the function, we allocate the return address slot to be able
3511 to spill the register for a long branch. */
3513 /* Define the register classes for local purposes. */
3514 enum reg_type
{ general
, mdb
, mdc
, floating
, last_type
};
3516 #define GET_REG_TYPE(regno) \
3517 (GP_REGISTER_P (regno) ? general : \
3518 (regno) == MDB_REGNUM ? mdb : \
3519 (regno) == MDC_REGNUM ? mdc : \
3522 /* First regno of each register type. */
3523 const int first_regno
[last_type
] = {0, MDB_REGNUM
, MDC_REGNUM
, FP_FIRST_REGNUM
};
3525 /* Size in bytes of each register type. */
3526 const int reg_type_size
[last_type
] = {4, 8, 4, 4};
3528 /* Structure to be filled in by visium_compute_frame_size. */
3529 struct visium_frame_info
3531 unsigned int save_area_size
; /* # bytes in the reg parm save area. */
3532 unsigned int reg_size1
; /* # bytes to store first block of regs. */
3533 unsigned int reg_size2
; /* # bytes to store second block of regs. */
3534 unsigned int max_reg1
; /* max. regno in first block */
3535 unsigned int var_size
; /* # bytes that variables take up. */
3536 unsigned int save_fp
; /* Nonzero if fp must be saved. */
3537 unsigned int save_lr
; /* Nonzero if lr must be saved. */
3538 unsigned int lr_slot
; /* Nonzero if the lr slot is needed. */
3539 unsigned int combine
; /* Nonzero if we can combine the allocation of
3540 variables and regs. */
3541 unsigned int interrupt
; /* Nonzero if the function is an interrupt
3543 unsigned int mask
[last_type
]; /* Masks of saved regs: gp, mdb, mdc, fp */
3546 /* Current frame information calculated by visium_compute_frame_size. */
3547 static struct visium_frame_info current_frame_info
;
3549 /* Accessor for current_frame_info.save_fp. */
3552 current_function_saves_fp (void)
3554 return current_frame_info
.save_fp
!= 0;
3557 /* Accessor for current_frame_info.save_lr. */
3560 current_function_saves_lr (void)
3562 return current_frame_info
.save_lr
!= 0;
3565 /* Accessor for current_frame_info.lr_slot. */
3568 current_function_has_lr_slot (void)
3570 return current_frame_info
.lr_slot
!= 0;
3573 /* Return non-zero if register REGNO needs to be saved in the frame. */
3576 visium_save_reg_p (int interrupt
, int regno
)
3580 case HARD_FRAME_POINTER_REGNUM
:
3581 /* This register is call-saved but handled specially. */
3585 /* This register is fixed but can be modified. */
3590 /* These registers are fixed and hold the interrupt context. */
3591 return (interrupt
!= 0);
3594 /* The other fixed registers are either immutable or special. */
3595 if (fixed_regs
[regno
])
3604 if (df_regs_ever_live_p (regno
))
3607 else if (call_used_regs
[regno
])
3610 /* To save mdb requires two temporary registers. To save mdc or
3611 any of the floating registers requires one temporary
3612 register. If this is an interrupt routine, the temporary
3613 registers need to be saved as well. These temporary registers
3614 are call used, so we only need deal with the case of leaf
3616 if (regno
== PROLOGUE_TMP_REGNUM
)
3618 if (df_regs_ever_live_p (MDB_REGNUM
)
3619 || df_regs_ever_live_p (MDC_REGNUM
))
3622 for (int i
= FP_FIRST_REGNUM
; i
<= FP_LAST_REGNUM
; i
++)
3623 if (df_regs_ever_live_p (i
))
3627 else if (regno
== PROLOGUE_TMP_REGNUM
+ 1)
3629 if (df_regs_ever_live_p (MDB_REGNUM
))
3634 return df_regs_ever_live_p (regno
) && !call_used_regs
[regno
];
3637 /* Compute the frame size required by the function. This function is called
3638 during the reload pass and also by visium_expand_prologue. */
3641 visium_compute_frame_size (int size
)
3643 const int save_area_size
= visium_reg_parm_save_area_size
;
3644 const int var_size
= VISIUM_STACK_ALIGN (size
);
3646 = frame_pointer_needed
|| df_regs_ever_live_p (HARD_FRAME_POINTER_REGNUM
);
3647 const int save_lr
= frame_pointer_needed
|| !crtl
->is_leaf
;
3648 const int lr_slot
= !save_lr
&& df_regs_ever_live_p (long_branch_regnum
);
3649 const int local_frame_offset
3650 = (save_fp
+ save_lr
+ lr_slot
) * UNITS_PER_WORD
;
3651 const int interrupt
= visium_interrupt_function_p ();
3652 unsigned int mask
[last_type
];
3661 memset (mask
, 0, last_type
* sizeof (unsigned int));
3663 /* The registers may need stacking in 2 blocks since only 32 32-bit words
3664 can be indexed from a given base address. */
3665 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
3667 if (visium_save_reg_p (interrupt
, regno
))
3669 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3670 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3671 int nbytes
= reg_type_size
[reg_type
];
3673 if (reg_size1
+ nbytes
> 32 * UNITS_PER_WORD
)
3676 reg_size1
+= nbytes
;
3678 mask
[reg_type
] |= mask_bit
;
3682 for (regno
= max_reg1
+ 1; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
3684 if (visium_save_reg_p (interrupt
, regno
))
3686 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3687 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3688 int nbytes
= reg_type_size
[reg_type
];
3690 reg_size2
+= nbytes
;
3691 mask
[reg_type
] |= mask_bit
;
3695 reg_size
= reg_size2
? reg_size2
: reg_size1
;
3696 combine
= (local_frame_offset
+ var_size
+ reg_size
) <= 32 * UNITS_PER_WORD
;
3698 = local_frame_offset
+ var_size
+ reg_size2
+ reg_size1
+ save_area_size
;
3700 current_frame_info
.save_area_size
= save_area_size
;
3701 current_frame_info
.reg_size1
= reg_size1
;
3702 current_frame_info
.max_reg1
= max_reg1
;
3703 current_frame_info
.reg_size2
= reg_size2
;
3704 current_frame_info
.var_size
= var_size
;
3705 current_frame_info
.save_fp
= save_fp
;
3706 current_frame_info
.save_lr
= save_lr
;
3707 current_frame_info
.lr_slot
= lr_slot
;
3708 current_frame_info
.combine
= combine
;
3709 current_frame_info
.interrupt
= interrupt
;
3711 memcpy (current_frame_info
.mask
, mask
, last_type
* sizeof (unsigned int));
3716 /* Helper function for INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET). Define
3717 the offset between two registers, one to be eliminated, and the other its
3718 replacement, at the start of a routine. */
3721 visium_initial_elimination_offset (int from
, int to ATTRIBUTE_UNUSED
)
3723 const int save_fp
= current_frame_info
.save_fp
;
3724 const int save_lr
= current_frame_info
.save_lr
;
3725 const int lr_slot
= current_frame_info
.lr_slot
;
3728 if (from
== FRAME_POINTER_REGNUM
)
3729 offset
= (save_fp
+ save_lr
+ lr_slot
) * UNITS_PER_WORD
;
3730 else if (from
== ARG_POINTER_REGNUM
)
3731 offset
= visium_compute_frame_size (get_frame_size ());
3738 /* For an interrupt handler, we may be saving call-clobbered registers.
3739 Say the epilogue uses these in addition to the link register. */
3742 visium_epilogue_uses (int regno
)
3744 if (regno
== LINK_REGNUM
)
3747 if (reload_completed
)
3749 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3750 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3752 return (current_frame_info
.mask
[reg_type
] & mask_bit
) != 0;
3758 /* Wrapper around emit_insn that sets RTX_FRAME_RELATED_P on the insn. */
3761 emit_frame_insn (rtx x
)
3764 RTX_FRAME_RELATED_P (x
) = 1;
3768 /* Allocate ALLOC bytes on the stack and save the registers LOW_REGNO to
3769 HIGH_REGNO at OFFSET from the stack pointer. */
3772 visium_save_regs (int alloc
, int offset
, int low_regno
, int high_regno
)
3774 /* If this is an interrupt handler function, then mark the register
3775 stores as volatile. This will prevent the instruction scheduler
3776 from scrambling the order of register saves. */
3777 const int volatile_p
= current_frame_info
.interrupt
;
3780 /* Allocate the stack space. */
3781 emit_frame_insn (gen_addsi3_flags (stack_pointer_rtx
, stack_pointer_rtx
,
3784 for (regno
= low_regno
; regno
<= high_regno
; regno
++)
3786 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3787 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3790 if (current_frame_info
.mask
[reg_type
] & mask_bit
)
3792 offset
-= reg_type_size
[reg_type
];
3798 = gen_frame_mem (SImode
,
3799 plus_constant (Pmode
,
3800 stack_pointer_rtx
, offset
));
3801 MEM_VOLATILE_P (mem
) = volatile_p
;
3802 emit_frame_insn (gen_movsi (mem
, gen_rtx_REG (SImode
, regno
)));
3808 rtx tmp
= gen_rtx_REG (DImode
, PROLOGUE_TMP_REGNUM
);
3810 = gen_frame_mem (DImode
,
3811 plus_constant (Pmode
,
3812 stack_pointer_rtx
, offset
));
3813 rtx reg
= gen_rtx_REG (DImode
, regno
);
3814 MEM_VOLATILE_P (mem
) = volatile_p
;
3815 emit_insn (gen_movdi (tmp
, reg
));
3816 /* Do not generate CFI if in interrupt handler. */
3818 emit_insn (gen_movdi (mem
, tmp
));
3821 insn
= emit_frame_insn (gen_movdi (mem
, tmp
));
3822 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3823 gen_rtx_SET (mem
, reg
));
3830 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
);
3832 = gen_frame_mem (SImode
,
3833 plus_constant (Pmode
,
3834 stack_pointer_rtx
, offset
));
3835 rtx reg
= gen_rtx_REG (SImode
, regno
);
3836 MEM_VOLATILE_P (mem
) = volatile_p
;
3837 emit_insn (gen_movsi (tmp
, reg
));
3838 insn
= emit_frame_insn (gen_movsi (mem
, tmp
));
3839 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3840 gen_rtx_SET (mem
, reg
));
3846 rtx tmp
= gen_rtx_REG (SFmode
, PROLOGUE_TMP_REGNUM
);
3848 = gen_frame_mem (SFmode
,
3849 plus_constant (Pmode
,
3850 stack_pointer_rtx
, offset
));
3851 rtx reg
= gen_rtx_REG (SFmode
, regno
);
3852 MEM_VOLATILE_P (mem
) = volatile_p
;
3853 emit_insn (gen_movsf (tmp
, reg
));
3854 insn
= emit_frame_insn (gen_movsf (mem
, tmp
));
3855 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3856 gen_rtx_SET (mem
, reg
));
3867 /* This function generates the code for function entry. */
3870 visium_expand_prologue (void)
3872 const int frame_size
= visium_compute_frame_size (get_frame_size ());
3873 const int save_area_size
= current_frame_info
.save_area_size
;
3874 const int reg_size1
= current_frame_info
.reg_size1
;
3875 const int max_reg1
= current_frame_info
.max_reg1
;
3876 const int reg_size2
= current_frame_info
.reg_size2
;
3877 const int var_size
= current_frame_info
.var_size
;
3878 const int save_fp
= current_frame_info
.save_fp
;
3879 const int save_lr
= current_frame_info
.save_lr
;
3880 const int lr_slot
= current_frame_info
.lr_slot
;
3881 const int local_frame_offset
3882 = (save_fp
+ save_lr
+ lr_slot
) * UNITS_PER_WORD
;
3883 const int combine
= current_frame_info
.combine
;
3888 /* Save the frame size for future references. */
3889 visium_frame_size
= frame_size
;
3891 if (flag_stack_usage_info
)
3892 current_function_static_stack_size
= frame_size
;
3894 /* If the registers have to be stacked in 2 blocks, stack the first one. */
3897 visium_save_regs (reg_size1
+ save_area_size
, reg_size1
, 0, max_reg1
);
3898 reg_size
= reg_size2
;
3899 first_reg
= max_reg1
+ 1;
3900 fsize
= local_frame_offset
+ var_size
+ reg_size2
;
3904 reg_size
= reg_size1
;
3906 fsize
= local_frame_offset
+ var_size
+ reg_size1
+ save_area_size
;
3909 /* If we can't combine register stacking with variable allocation, partially
3910 allocate and stack the (remaining) registers now. */
3911 if (reg_size
&& !combine
)
3912 visium_save_regs (fsize
- local_frame_offset
- var_size
, reg_size
,
3913 first_reg
, FIRST_PSEUDO_REGISTER
- 1);
3915 /* If we can combine register stacking with variable allocation, fully
3916 allocate and stack the (remaining) registers now. */
3917 if (reg_size
&& combine
)
3918 visium_save_regs (fsize
, local_frame_offset
+ var_size
+ reg_size
,
3919 first_reg
, FIRST_PSEUDO_REGISTER
- 1);
3921 /* Otherwise space may still need to be allocated for the variables. */
3924 const int alloc_size
= reg_size
? local_frame_offset
+ var_size
: fsize
;
3926 if (alloc_size
> 65535)
3928 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
), insn
;
3929 emit_insn (gen_movsi (tmp
, GEN_INT (alloc_size
)));
3930 insn
= emit_frame_insn (gen_subsi3_flags (stack_pointer_rtx
,
3933 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3934 gen_rtx_SET (stack_pointer_rtx
,
3935 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
3936 GEN_INT (-alloc_size
))));
3939 emit_frame_insn (gen_addsi3_flags (stack_pointer_rtx
,
3941 GEN_INT (-alloc_size
)));
3945 emit_frame_insn (gen_movsi (gen_frame_mem (SImode
, stack_pointer_rtx
),
3946 hard_frame_pointer_rtx
));
3948 if (frame_pointer_needed
)
3949 emit_frame_insn (gen_stack_save ());
3955 /* Normally the frame pointer and link register get saved via
3960 Indexing off sp rather than fp to store the link register
3961 avoids presenting the instruction scheduler with an initial
3962 pipeline hazard. If however the frame is needed for eg.
3963 __builtin_return_address which needs to retrieve the saved
3964 value of the link register from the stack at fp + 4 then
3965 indexing from sp can confuse the dataflow, causing the link
3966 register to be retrieved before it has been saved. */
3967 if (cfun
->machine
->frame_needed
)
3968 base_rtx
= hard_frame_pointer_rtx
;
3970 base_rtx
= stack_pointer_rtx
;
3972 mem
= gen_frame_mem (SImode
,
3973 plus_constant (Pmode
,
3974 base_rtx
, save_fp
* UNITS_PER_WORD
));
3975 emit_frame_insn (gen_movsi (mem
, gen_rtx_REG (SImode
, LINK_REGNUM
)));
3979 static GTY(()) rtx cfa_restores
;
3981 /* Queue a REG_CFA_RESTORE note until next stack manipulation insn. */
3984 visium_add_cfa_restore_note (rtx reg
)
3986 cfa_restores
= alloc_reg_note (REG_CFA_RESTORE
, reg
, cfa_restores
);
3989 /* Add queued REG_CFA_RESTORE notes to INSN, if any. */
3992 visium_add_queued_cfa_restore_notes (rtx insn
)
3997 for (last
= cfa_restores
; XEXP (last
, 1); last
= XEXP (last
, 1))
3999 XEXP (last
, 1) = REG_NOTES (insn
);
4000 REG_NOTES (insn
) = cfa_restores
;
4001 cfa_restores
= NULL_RTX
;
4004 /* Restore the registers LOW_REGNO to HIGH_REGNO from the save area at OFFSET
4005 from the stack pointer and pop DEALLOC bytes off the stack. */
4008 visium_restore_regs (int dealloc
, int offset
, int high_regno
, int low_regno
)
4010 /* If this is an interrupt handler function, then mark the register
4011 restores as volatile. This will prevent the instruction scheduler
4012 from scrambling the order of register restores. */
4013 const int volatile_p
= current_frame_info
.interrupt
;
4014 int r30_offset
= -1;
4017 for (regno
= high_regno
; regno
>= low_regno
; --regno
)
4019 enum reg_type reg_type
= GET_REG_TYPE (regno
);
4020 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
4022 if (current_frame_info
.mask
[reg_type
] & mask_bit
)
4027 /* Postpone restoring the interrupted context registers
4028 until last, since they need to be preceded by a dsi. */
4031 else if (regno
== 30)
4032 r30_offset
= offset
;
4036 = gen_frame_mem (SImode
,
4037 plus_constant (Pmode
,
4040 rtx reg
= gen_rtx_REG (SImode
, regno
);
4041 MEM_VOLATILE_P (mem
) = volatile_p
;
4042 emit_insn (gen_movsi (reg
, mem
));
4043 visium_add_cfa_restore_note (reg
);
4049 rtx tmp
= gen_rtx_REG (DImode
, PROLOGUE_TMP_REGNUM
);
4051 = gen_frame_mem (DImode
,
4052 plus_constant (Pmode
,
4053 stack_pointer_rtx
, offset
));
4054 rtx reg
= gen_rtx_REG (DImode
, regno
);
4055 MEM_VOLATILE_P (mem
) = volatile_p
;
4056 emit_insn (gen_movdi (tmp
, mem
));
4057 emit_insn (gen_movdi (reg
, tmp
));
4058 /* Do not generate CFI if in interrupt handler. */
4060 visium_add_cfa_restore_note (reg
);
4066 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
);
4068 = gen_frame_mem (SImode
,
4069 plus_constant (Pmode
,
4070 stack_pointer_rtx
, offset
));
4071 rtx reg
= gen_rtx_REG (SImode
, regno
);
4072 MEM_VOLATILE_P (mem
) = volatile_p
;
4073 emit_insn (gen_movsi (tmp
, mem
));
4074 emit_insn (gen_movsi (reg
, tmp
));
4075 visium_add_cfa_restore_note (reg
);
4081 rtx tmp
= gen_rtx_REG (SFmode
, PROLOGUE_TMP_REGNUM
);
4083 = gen_frame_mem (SFmode
,
4084 plus_constant (Pmode
,
4085 stack_pointer_rtx
, offset
));
4086 rtx reg
= gen_rtx_REG (SFmode
, regno
);
4087 MEM_VOLATILE_P (mem
) = volatile_p
;
4088 emit_insn (gen_movsf (tmp
, mem
));
4089 emit_insn (gen_movsf (reg
, tmp
));
4090 visium_add_cfa_restore_note (reg
);
4098 offset
+= reg_type_size
[reg_type
];
4102 /* If the interrupted context needs to be restored, precede the
4103 restores of r29 and r30 by a dsi. */
4104 if (r30_offset
>= 0)
4106 emit_insn (gen_dsi ());
4107 emit_move_insn (gen_rtx_REG (SImode
, 30),
4108 gen_frame_mem (SImode
,
4109 plus_constant (Pmode
,
4112 emit_move_insn (gen_rtx_REG (SImode
, 29),
4113 gen_frame_mem (SImode
,
4114 plus_constant (Pmode
,
4119 /* Deallocate the stack space. */
4120 rtx insn
= emit_frame_insn (gen_stack_pop (GEN_INT (dealloc
)));
4121 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
4122 gen_rtx_SET (stack_pointer_rtx
,
4123 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
4124 GEN_INT (dealloc
))));
4125 visium_add_queued_cfa_restore_notes (insn
);
4128 /* This function generates the code for function exit. */
4131 visium_expand_epilogue (void)
4133 const int save_area_size
= current_frame_info
.save_area_size
;
4134 const int reg_size1
= current_frame_info
.reg_size1
;
4135 const int max_reg1
= current_frame_info
.max_reg1
;
4136 const int reg_size2
= current_frame_info
.reg_size2
;
4137 const int var_size
= current_frame_info
.var_size
;
4138 const int restore_fp
= current_frame_info
.save_fp
;
4139 const int restore_lr
= current_frame_info
.save_lr
;
4140 const int lr_slot
= current_frame_info
.lr_slot
;
4141 const int local_frame_offset
4142 = (restore_fp
+ restore_lr
+ lr_slot
) * UNITS_PER_WORD
;
4143 const int combine
= current_frame_info
.combine
;
4148 /* Do not bother restoring the stack pointer if it hasn't been changed in
4149 the function since it was saved _after_ the allocation of the frame. */
4150 if (!crtl
->sp_is_unchanging
)
4151 emit_insn (gen_stack_restore ());
4153 /* Restore the frame pointer if necessary. The usual code would be:
4158 but for the MCM this constitutes a stall/hazard so it is changed to:
4163 if the stack pointer has actually been restored. */
4168 if (TARGET_MCM
&& !crtl
->sp_is_unchanging
)
4169 src
= gen_frame_mem (SImode
, hard_frame_pointer_rtx
);
4171 src
= gen_frame_mem (SImode
, stack_pointer_rtx
);
4173 rtx insn
= emit_frame_insn (gen_movsi (hard_frame_pointer_rtx
, src
));
4174 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
4175 gen_rtx_SET (stack_pointer_rtx
,
4176 hard_frame_pointer_rtx
));
4177 visium_add_cfa_restore_note (hard_frame_pointer_rtx
);
4180 /* Restore the link register if necessary. */
4183 rtx mem
= gen_frame_mem (SImode
,
4184 plus_constant (Pmode
,
4186 restore_fp
* UNITS_PER_WORD
));
4187 rtx reg
= gen_rtx_REG (SImode
, LINK_REGNUM
);
4188 emit_insn (gen_movsi (reg
, mem
));
4189 visium_add_cfa_restore_note (reg
);
4192 /* If we have two blocks of registers, deal with the second one first. */
4195 reg_size
= reg_size2
;
4196 last_reg
= max_reg1
+ 1;
4197 fsize
= local_frame_offset
+ var_size
+ reg_size2
;
4201 reg_size
= reg_size1
;
4203 fsize
= local_frame_offset
+ var_size
+ reg_size1
+ save_area_size
;
4206 /* If the variable allocation could be combined with register stacking,
4207 restore the (remaining) registers and fully deallocate now. */
4208 if (reg_size
&& combine
)
4209 visium_restore_regs (fsize
, local_frame_offset
+ var_size
,
4210 FIRST_PSEUDO_REGISTER
- 1, last_reg
);
4212 /* Otherwise deallocate the variables first. */
4215 const int pop_size
= reg_size
? local_frame_offset
+ var_size
: fsize
;
4218 if (pop_size
> 65535)
4220 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
);
4221 emit_move_insn (tmp
, GEN_INT (pop_size
));
4222 insn
= emit_frame_insn (gen_stack_pop (tmp
));
4225 insn
= emit_frame_insn (gen_stack_pop (GEN_INT (pop_size
)));
4226 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
4227 gen_rtx_SET (stack_pointer_rtx
,
4228 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
4229 GEN_INT (pop_size
))));
4230 visium_add_queued_cfa_restore_notes (insn
);
4233 /* If the variable allocation couldn't be combined with register stacking,
4234 restore the (remaining) registers now and partially deallocate. */
4235 if (reg_size
&& !combine
)
4236 visium_restore_regs (fsize
- local_frame_offset
- var_size
, 0,
4237 FIRST_PSEUDO_REGISTER
- 1, last_reg
);
4239 /* If the first block of registers has yet to be restored, do it now. */
4241 visium_restore_regs (reg_size1
+ save_area_size
, 0, max_reg1
, 0);
4243 /* If this is an exception return, make the necessary stack adjustment. */
4244 if (crtl
->calls_eh_return
)
4245 emit_insn (gen_stack_pop (EH_RETURN_STACKADJ_RTX
));
4248 /* Return true if it is appropriate to emit `return' instructions in the
4249 body of a function. */
4252 visium_can_use_return_insn_p (void)
4254 return reload_completed
4255 && visium_frame_size
== 0
4256 && !visium_interrupt_function_p ();
4259 /* Return the register class required for an intermediate register used to
4260 copy a register of RCLASS from/to X. If no such intermediate register is
4261 required, return NO_REGS. If more than one such intermediate register is
4262 required, describe the one that is closest in the copy chain to the reload
4266 visium_secondary_reload (bool in_p ATTRIBUTE_UNUSED
, rtx x
,
4268 machine_mode mode ATTRIBUTE_UNUSED
,
4269 secondary_reload_info
*sri ATTRIBUTE_UNUSED
)
4271 int regno
= true_regnum (x
);
4273 /* For MDB, MDC and FP_REGS, a general register is needed for a move to
4275 if (regno
== -1 && (rclass
== MDB
|| rclass
== MDC
|| rclass
== FP_REGS
))
4276 return GENERAL_REGS
;
4278 /* Moves between MDB, MDC and FP_REGS also require a general register. */
4279 else if (((regno
== R_MDB
|| regno
== R_MDC
) && rclass
== FP_REGS
)
4280 || (FP_REGISTER_P (regno
) && (rclass
== MDB
|| rclass
== MDC
)))
4281 return GENERAL_REGS
;
4283 /* Finally an (unlikely ?) move between MDB and MDC needs a general reg. */
4284 else if ((regno
== R_MDB
&& rclass
== MDC
)
4285 || (rclass
== MDB
&& regno
== R_MDC
))
4286 return GENERAL_REGS
;
4291 /* Return true if pseudos that have been assigned to registers of RCLASS
4292 would likely be spilled because registers of RCLASS are needed for
4296 visium_class_likely_spilled_p (reg_class_t rclass ATTRIBUTE_UNUSED
)
4298 /* Return false for classes R1, R2 and R3, which are intended to be used
4299 only in the source code in conjunction with block move instructions. */
4303 /* Return the register number if OP is a REG or a SUBREG of a REG, and
4304 INVALID_REGNUM in all the other cases. */
4307 reg_or_subreg_regno (rtx op
)
4311 if (GET_CODE (op
) == REG
)
4313 else if (GET_CODE (op
) == SUBREG
&& GET_CODE (SUBREG_REG (op
)) == REG
)
4315 if (REGNO (SUBREG_REG (op
)) < FIRST_PSEUDO_REGISTER
)
4316 regno
= subreg_regno (op
);
4318 regno
= REGNO (SUBREG_REG (op
));
4321 regno
= INVALID_REGNUM
;
4326 /* Implement TARGET_CAN_CHANGE_MODE_CLASS.
4328 It's not obvious from the documentation of the hook that MDB cannot
4329 change mode. However difficulties arise from expressions of the form
4331 (subreg:SI (reg:DI R_MDB) 0)
4333 There is no way to convert that reference to a single machine
4334 register and, without the following definition, reload will quietly
4340 visium_can_change_mode_class (machine_mode from
, machine_mode to
,
4343 return (rclass
!= MDB
|| GET_MODE_SIZE (from
) == GET_MODE_SIZE (to
));
4346 #include "gt-visium.h"