1 /* Output routines for Visium.
2 Copyright (C) 2002-2016 Free Software Foundation, Inc.
3 Contributed by C.Nettleton, J.P.Parkes and P.Garbett.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
28 #include "gimple-expr.h"
32 #include "stringpool.h"
38 #include "diagnostic-core.h"
41 #include "fold-const.h"
42 #include "stor-layout.h"
46 #include "insn-attr.h"
50 #include "langhooks.h"
52 #include "tm-constrs.h"
54 #include "tree-pass.h"
58 /* This file should be included last. */
59 #include "target-def.h"
61 /* Enumeration of indexes into machine_libfunc_table. */
62 enum machine_libfunc_index
72 MLTI_set_trampoline_parity
,
77 struct GTY(()) machine_libfuncs
82 /* The table of Visium-specific libfuncs. */
83 static GTY(()) struct machine_libfuncs visium_libfuncs
;
85 #define vlt visium_libfuncs.table
87 /* Accessor macros for visium_libfuncs. */
88 #define long_int_memcpy_libfunc (vlt[MLTI_long_int_memcpy])
89 #define wrd_memcpy_libfunc (vlt[MLTI_wrd_memcpy])
90 #define byt_memcpy_libfunc (vlt[MLTI_byt_memcpy])
91 #define long_int_memset_libfunc (vlt[MLTI_long_int_memset])
92 #define wrd_memset_libfunc (vlt[MLTI_wrd_memset])
93 #define byt_memset_libfunc (vlt[MLTI_byt_memset])
94 #define set_trampoline_parity_libfunc (vlt[MLTI_set_trampoline_parity])
96 /* Machine specific function data. */
97 struct GTY (()) machine_function
99 /* Size of the frame of the function. */
102 /* Size of the reg parm save area, non-zero only for functions with variable
103 argument list. We cannot use the crtl->args.pretend_args_size machinery
104 for this purpose because this size is added to virtual_incoming_args_rtx
105 to give the location of the first parameter passed by the caller on the
106 stack and virtual_incoming_args_rtx is also the location of the first
107 parameter on the stack. So crtl->args.pretend_args_size can be non-zero
108 only if the first non-register named parameter is not passed entirely on
109 the stack and this runs afoul of the need to have a reg parm save area
110 even with a variable argument list starting on the stack because of the
111 separate handling of general and floating-point registers. */
112 int reg_parm_save_area_size
;
114 /* True if we have created an rtx which relies on the frame pointer. */
117 /* True if we have exposed the flags register. From this moment on, we
118 cannot generate simple operations for integer registers. We could
119 use reload_completed for this purpose, but this would cripple the
120 postreload CSE and GCSE passes which run before postreload split. */
124 #define visium_frame_size cfun->machine->frame_size
125 #define visium_reg_parm_save_area_size cfun->machine->reg_parm_save_area_size
126 #define visium_frame_needed cfun->machine->frame_needed
127 #define visium_flags_exposed cfun->machine->flags_exposed
129 /* 1 if the next opcode is to be specially indented. */
130 int visium_indent_opcode
= 0;
132 /* Register number used for long branches when LR isn't available. It
133 must be a call-used register since it isn't saved on function entry.
134 We do not care whether the branch is predicted or not on the GR6,
135 given how unlikely it is to have a long branch in a leaf function. */
136 static unsigned int long_branch_regnum
= 31;
138 static tree
visium_handle_interrupt_attr (tree
*, tree
, tree
, int, bool *);
139 static inline bool current_function_saves_fp (void);
140 static inline bool current_function_saves_lr (void);
141 static inline bool current_function_has_lr_slot (void);
143 /* Supported attributes:
144 interrupt -- specifies this function is an interrupt handler. */
145 static const struct attribute_spec visium_attribute_table
[] =
147 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
148 affects_type_identity } */
149 {"interrupt", 0, 0, true, false, false, visium_handle_interrupt_attr
, false},
150 {NULL
, 0, 0, false, false, false, NULL
, false}
153 static struct machine_function
*visium_init_machine_status (void);
155 /* Target hooks and TARGET_INITIALIZER */
157 static bool visium_pass_by_reference (cumulative_args_t
, enum machine_mode
,
160 static rtx
visium_function_arg (cumulative_args_t
, enum machine_mode
,
163 static void visium_function_arg_advance (cumulative_args_t
, enum machine_mode
,
166 static bool visium_return_in_memory (const_tree
, const_tree fntype
);
168 static rtx
visium_function_value (const_tree
, const_tree fn_decl_or_type
,
171 static rtx
visium_libcall_value (enum machine_mode
, const_rtx
);
173 static void visium_setup_incoming_varargs (cumulative_args_t
,
177 static void visium_va_start (tree valist
, rtx nextarg
);
179 static tree
visium_gimplify_va_arg (tree
, tree
, gimple_seq
*, gimple_seq
*);
181 static bool visium_function_ok_for_sibcall (tree
, tree
);
183 static bool visium_frame_pointer_required (void);
185 static tree
visium_build_builtin_va_list (void);
187 static rtx_insn
*visium_md_asm_adjust (vec
<rtx
> &, vec
<rtx
> &,
189 vec
<rtx
> &, HARD_REG_SET
&);
191 static bool visium_legitimate_constant_p (enum machine_mode
, rtx
);
193 static bool visium_legitimate_address_p (enum machine_mode
, rtx
, bool);
195 static bool visium_print_operand_punct_valid_p (unsigned char);
196 static void visium_print_operand (FILE *, rtx
, int);
197 static void visium_print_operand_address (FILE *, machine_mode
, rtx
);
199 static void visium_conditional_register_usage (void);
201 static rtx
visium_legitimize_address (rtx
, rtx
, enum machine_mode
);
203 static reg_class_t
visium_secondary_reload (bool, rtx
, reg_class_t
,
205 secondary_reload_info
*);
207 static bool visium_class_likely_spilled_p (reg_class_t
);
209 static void visium_trampoline_init (rtx
, tree
, rtx
);
211 static int visium_issue_rate (void);
213 static int visium_adjust_priority (rtx_insn
*, int);
215 static int visium_adjust_cost (rtx_insn
*, int, rtx_insn
*, int, unsigned int);
217 static int visium_register_move_cost (enum machine_mode
, reg_class_t
,
220 static int visium_memory_move_cost (enum machine_mode
, reg_class_t
, bool);
222 static bool visium_rtx_costs (rtx
, machine_mode
, int, int, int *, bool);
224 static void visium_option_override (void);
226 static void visium_init_libfuncs (void);
228 static unsigned int visium_reorg (void);
230 /* Setup the global target hooks structure. */
232 #undef TARGET_MAX_ANCHOR_OFFSET
233 #define TARGET_MAX_ANCHOR_OFFSET 31
235 #undef TARGET_PASS_BY_REFERENCE
236 #define TARGET_PASS_BY_REFERENCE visium_pass_by_reference
238 #undef TARGET_FUNCTION_ARG
239 #define TARGET_FUNCTION_ARG visium_function_arg
241 #undef TARGET_FUNCTION_ARG_ADVANCE
242 #define TARGET_FUNCTION_ARG_ADVANCE visium_function_arg_advance
244 #undef TARGET_RETURN_IN_MEMORY
245 #define TARGET_RETURN_IN_MEMORY visium_return_in_memory
247 #undef TARGET_FUNCTION_VALUE
248 #define TARGET_FUNCTION_VALUE visium_function_value
250 #undef TARGET_LIBCALL_VALUE
251 #define TARGET_LIBCALL_VALUE visium_libcall_value
253 #undef TARGET_SETUP_INCOMING_VARARGS
254 #define TARGET_SETUP_INCOMING_VARARGS visium_setup_incoming_varargs
256 #undef TARGET_EXPAND_BUILTIN_VA_START
257 #define TARGET_EXPAND_BUILTIN_VA_START visium_va_start
259 #undef TARGET_BUILD_BUILTIN_VA_LIST
260 #define TARGET_BUILD_BUILTIN_VA_LIST visium_build_builtin_va_list
262 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
263 #define TARGET_GIMPLIFY_VA_ARG_EXPR visium_gimplify_va_arg
265 #undef TARGET_LEGITIMATE_CONSTANT_P
266 #define TARGET_LEGITIMATE_CONSTANT_P visium_legitimate_constant_p
269 #define TARGET_LRA_P hook_bool_void_false
271 #undef TARGET_LEGITIMATE_ADDRESS_P
272 #define TARGET_LEGITIMATE_ADDRESS_P visium_legitimate_address_p
274 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
275 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P visium_print_operand_punct_valid_p
276 #undef TARGET_PRINT_OPERAND
277 #define TARGET_PRINT_OPERAND visium_print_operand
278 #undef TARGET_PRINT_OPERAND_ADDRESS
279 #define TARGET_PRINT_OPERAND_ADDRESS visium_print_operand_address
281 #undef TARGET_ATTRIBUTE_TABLE
282 #define TARGET_ATTRIBUTE_TABLE visium_attribute_table
284 #undef TARGET_ADDRESS_COST
285 #define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
287 #undef TARGET_STRICT_ARGUMENT_NAMING
288 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
290 #undef TARGET_SCHED_ISSUE_RATE
291 #define TARGET_SCHED_ISSUE_RATE visium_issue_rate
293 #undef TARGET_SCHED_ADJUST_PRIORITY
294 #define TARGET_SCHED_ADJUST_PRIORITY visium_adjust_priority
296 #undef TARGET_SCHED_ADJUST_COST
297 #define TARGET_SCHED_ADJUST_COST visium_adjust_cost
299 #undef TARGET_MEMORY_MOVE_COST
300 #define TARGET_MEMORY_MOVE_COST visium_memory_move_cost
302 #undef TARGET_REGISTER_MOVE_COST
303 #define TARGET_REGISTER_MOVE_COST visium_register_move_cost
305 #undef TARGET_RTX_COSTS
306 #define TARGET_RTX_COSTS visium_rtx_costs
308 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
309 #define TARGET_FUNCTION_OK_FOR_SIBCALL visium_function_ok_for_sibcall
311 #undef TARGET_FRAME_POINTER_REQUIRED
312 #define TARGET_FRAME_POINTER_REQUIRED visium_frame_pointer_required
314 #undef TARGET_SECONDARY_RELOAD
315 #define TARGET_SECONDARY_RELOAD visium_secondary_reload
317 #undef TARGET_CLASS_LIKELY_SPILLED_P
318 #define TARGET_CLASS_LIKELY_SPILLED_P visium_class_likely_spilled_p
320 #undef TARGET_LEGITIMIZE_ADDRESS
321 #define TARGET_LEGITIMIZE_ADDRESS visium_legitimize_address
323 #undef TARGET_OPTION_OVERRIDE
324 #define TARGET_OPTION_OVERRIDE visium_option_override
326 #undef TARGET_INIT_LIBFUNCS
327 #define TARGET_INIT_LIBFUNCS visium_init_libfuncs
329 #undef TARGET_CONDITIONAL_REGISTER_USAGE
330 #define TARGET_CONDITIONAL_REGISTER_USAGE visium_conditional_register_usage
332 #undef TARGET_TRAMPOLINE_INIT
333 #define TARGET_TRAMPOLINE_INIT visium_trampoline_init
335 #undef TARGET_MD_ASM_ADJUST
336 #define TARGET_MD_ASM_ADJUST visium_md_asm_adjust
338 #undef TARGET_FLAGS_REGNUM
339 #define TARGET_FLAGS_REGNUM FLAGS_REGNUM
341 struct gcc_target targetm
= TARGET_INITIALIZER
;
345 const pass_data pass_data_visium_reorg
=
349 OPTGROUP_NONE
, /* optinfo_flags */
350 TV_MACH_DEP
, /* tv_id */
351 0, /* properties_required */
352 0, /* properties_provided */
353 0, /* properties_destroyed */
354 0, /* todo_flags_start */
355 0, /* todo_flags_finish */
358 class pass_visium_reorg
: public rtl_opt_pass
361 pass_visium_reorg(gcc::context
*ctxt
)
362 : rtl_opt_pass(pass_data_visium_reorg
, ctxt
)
365 /* opt_pass methods: */
366 virtual unsigned int execute (function
*)
368 return visium_reorg ();
371 }; // class pass_work_around_errata
376 make_pass_visium_reorg (gcc::context
*ctxt
)
378 return new pass_visium_reorg (ctxt
);
381 /* Options override for Visium. */
384 visium_option_override (void)
387 warning (OPT_fpic
, "-fpic is not supported");
389 warning (OPT_fPIC
, "-fPIC is not supported");
391 /* MCM is the default in the GR5/GR6 era. */
392 target_flags
|= MASK_MCM
;
394 /* FPU is the default with MCM, but don't override an explicit option. */
395 if ((target_flags_explicit
& MASK_FPU
) == 0)
396 target_flags
|= MASK_FPU
;
398 /* The supervisor mode is the default. */
399 if ((target_flags_explicit
& MASK_SV_MODE
) == 0)
400 target_flags
|= MASK_SV_MODE
;
402 /* The GR6 has the Block Move Instructions and an IEEE-compliant FPU. */
403 if (visium_cpu_and_features
== PROCESSOR_GR6
)
405 target_flags
|= MASK_BMI
;
406 if (target_flags
& MASK_FPU
)
407 target_flags
|= MASK_FPU_IEEE
;
410 /* Set -mtune from -mcpu if not specified. */
411 if (!global_options_set
.x_visium_cpu
)
412 visium_cpu
= visium_cpu_and_features
;
414 /* Align functions on 256-byte (32-quadword) for GR5 and 64-byte (8-quadword)
415 boundaries for GR6 so they start a new burst mode window. */
416 if (align_functions
== 0)
418 if (visium_cpu
== PROCESSOR_GR6
)
419 align_functions
= 64;
421 align_functions
= 256;
423 /* Allow the size of compilation units to double because of inlining.
424 In practice the global size of the object code is hardly affected
425 because the additional instructions will take up the padding. */
426 maybe_set_param_value (PARAM_INLINE_UNIT_GROWTH
, 100,
427 global_options
.x_param_values
,
428 global_options_set
.x_param_values
);
431 /* Likewise for loops. */
432 if (align_loops
== 0)
434 if (visium_cpu
== PROCESSOR_GR6
)
439 /* But not if they are too far away from a 256-byte boundary. */
440 align_loops_max_skip
= 31;
444 /* Align all jumps on quadword boundaries for the burst mode, and even
445 on 8-quadword boundaries for GR6 so they start a new window. */
446 if (align_jumps
== 0)
448 if (visium_cpu
== PROCESSOR_GR6
)
454 /* We register a machine-specific pass. This pass must be scheduled as
455 late as possible so that we have the (essentially) final form of the
456 insn stream to work on. Registering the pass must be done at start up.
457 It's convenient to do it here. */
458 opt_pass
*visium_reorg_pass
= make_pass_visium_reorg (g
);
459 struct register_pass_info insert_pass_visium_reorg
=
461 visium_reorg_pass
, /* pass */
462 "dbr", /* reference_pass_name */
463 1, /* ref_pass_instance_number */
464 PASS_POS_INSERT_AFTER
/* po_op */
466 register_pass (&insert_pass_visium_reorg
);
469 /* Register the Visium-specific libfuncs with the middle-end. */
472 visium_init_libfuncs (void)
475 long_int_memcpy_libfunc
= init_one_libfunc ("__long_int_memcpy");
476 wrd_memcpy_libfunc
= init_one_libfunc ("__wrd_memcpy");
477 byt_memcpy_libfunc
= init_one_libfunc ("__byt_memcpy");
479 long_int_memset_libfunc
= init_one_libfunc ("__long_int_memset");
480 wrd_memset_libfunc
= init_one_libfunc ("__wrd_memset");
481 byt_memset_libfunc
= init_one_libfunc ("__byt_memset");
483 set_trampoline_parity_libfunc
= init_one_libfunc ("__set_trampoline_parity");
486 /* Return the number of instructions that can issue on the same cycle. */
489 visium_issue_rate (void)
504 /* Return the adjusted PRIORITY of INSN. */
507 visium_adjust_priority (rtx_insn
*insn
, int priority
)
509 /* On the GR5, we slightly increase the priority of writes in order to avoid
510 scheduling a read on the next cycle. This is necessary in addition to the
511 associated insn reservation because there are no data dependencies.
512 We also slightly increase the priority of reads from ROM in order to group
513 them as much as possible. These reads are a bit problematic because they
514 conflict with the instruction fetches, i.e. the data and instruction buses
515 tread on each other's toes when they are executed. */
516 if (visium_cpu
== PROCESSOR_GR5
519 && recog_memoized (insn
) >= 0)
521 enum attr_type attr_type
= get_attr_type (insn
);
522 if (attr_type
== TYPE_REG_MEM
523 || (attr_type
== TYPE_MEM_REG
524 && MEM_READONLY_P (SET_SRC (PATTERN (insn
)))))
531 /* Adjust the cost of a scheduling dependency. Return the new cost of
532 a dependency LINK of INSN on DEP_INSN. COST is the current cost. */
535 visium_adjust_cost (rtx_insn
*insn
, int dep_type
, rtx_insn
*dep_insn
, int cost
,
538 enum attr_type attr_type
;
540 /* Don't adjust costs for true dependencies as they are described with
541 bypasses. But we make an exception for the first scheduling pass to
542 help the subsequent postreload compare elimination pass. */
543 if (dep_type
== REG_DEP_TRUE
)
545 if (!reload_completed
546 && recog_memoized (insn
) >= 0
547 && get_attr_type (insn
) == TYPE_CMP
)
549 rtx pat
= PATTERN (insn
);
550 gcc_assert (GET_CODE (pat
) == SET
);
551 rtx src
= SET_SRC (pat
);
553 /* Only the branches can be modified by the postreload compare
554 elimination pass, not the cstores because they accept only
555 unsigned comparison operators and they are eliminated if
556 one of the operands is zero. */
557 if (GET_CODE (src
) == IF_THEN_ELSE
558 && XEXP (XEXP (src
, 0), 1) == const0_rtx
559 && recog_memoized (dep_insn
) >= 0)
561 enum attr_type dep_attr_type
= get_attr_type (dep_insn
);
563 /* The logical instructions use CCmode and thus work with any
564 comparison operator, whereas the arithmetic instructions use
565 CCNZmode and thus work with only a small subset. */
566 if (dep_attr_type
== TYPE_LOGIC
567 || (dep_attr_type
== TYPE_ARITH
568 && visium_nz_comparison_operator (XEXP (src
, 0),
578 if (recog_memoized (insn
) < 0)
581 attr_type
= get_attr_type (insn
);
583 /* Anti dependency: DEP_INSN reads a register that INSN writes some
585 if (dep_type
== REG_DEP_ANTI
)
587 /* On the GR5, the latency of FP instructions needs to be taken into
588 account for every dependency involving a write. */
589 if (attr_type
== TYPE_REG_FP
&& visium_cpu
== PROCESSOR_GR5
)
592 rtx pat
= PATTERN (insn
);
593 rtx dep_pat
= PATTERN (dep_insn
);
595 if (GET_CODE (pat
) != SET
|| GET_CODE (dep_pat
) != SET
)
596 /* If this happens, we have to extend this to schedule
597 optimally. Return 0 for now. */
600 if (reg_mentioned_p (SET_DEST (pat
), SET_SRC (dep_pat
)))
602 if (recog_memoized (dep_insn
) < 0)
605 switch (get_attr_type (dep_insn
))
613 /* A fload can't be issued until a preceding arithmetic
614 operation has finished if the target of the fload is
615 any of the sources (or destination) of the arithmetic
616 operation. Note that the latency may be (much)
617 greater than this if the preceding instruction
618 concerned is in a queue. */
619 return insn_default_latency (dep_insn
);
627 /* On the GR6, we try to make sure that the link register is restored
628 sufficiently ahead of the return as to yield a correct prediction
629 from the branch predictor. By default there is no true dependency
630 but an anti dependency between them, so we simply reuse it. */
631 else if (attr_type
== TYPE_RET
&& visium_cpu
== PROCESSOR_GR6
)
633 rtx dep_pat
= PATTERN (dep_insn
);
634 if (GET_CODE (dep_pat
) == SET
635 && REG_P (SET_DEST (dep_pat
))
636 && REGNO (SET_DEST (dep_pat
)) == LINK_REGNUM
)
640 /* For other anti dependencies, the cost is 0. */
644 /* Output dependency: DEP_INSN writes a register that INSN writes some
646 else if (dep_type
== REG_DEP_OUTPUT
)
648 /* On the GR5, the latency of FP instructions needs to be taken into
649 account for every dependency involving a write. */
650 if (attr_type
== TYPE_REG_FP
&& visium_cpu
== PROCESSOR_GR5
)
653 rtx pat
= PATTERN (insn
);
654 rtx dep_pat
= PATTERN (dep_insn
);
656 if (GET_CODE (pat
) != SET
|| GET_CODE (dep_pat
) != SET
)
657 /* If this happens, we have to extend this to schedule
658 optimally. Return 0 for now. */
661 if (reg_mentioned_p (SET_DEST (pat
), SET_DEST (dep_pat
)))
663 if (recog_memoized (dep_insn
) < 0)
666 switch (get_attr_type (dep_insn
))
674 /* A fload can't be issued until a preceding arithmetic
675 operation has finished if the target of the fload is
676 the destination of the arithmetic operation. Note that
677 the latency may be (much) greater than this if the
678 preceding instruction concerned is in a queue. */
679 return insn_default_latency (dep_insn
);
687 /* For other output dependencies, the cost is 0. */
694 /* Handle an "interrupt_handler" attribute; arguments as in
695 struct attribute_spec.handler. */
698 visium_handle_interrupt_attr (tree
*node
, tree name
,
699 tree args ATTRIBUTE_UNUSED
,
700 int flags ATTRIBUTE_UNUSED
,
703 if (TREE_CODE (*node
) != FUNCTION_DECL
)
705 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
707 *no_add_attrs
= true;
709 else if (!TARGET_SV_MODE
)
711 error ("an interrupt handler cannot be compiled with -muser-mode");
712 *no_add_attrs
= true;
718 /* Return non-zero if the current function is an interrupt function. */
721 visium_interrupt_function_p (void)
724 lookup_attribute ("interrupt",
725 DECL_ATTRIBUTES (current_function_decl
)) != NULL_TREE
;
728 /* Conditionally modify the settings of the register file. */
731 visium_conditional_register_usage (void)
733 /* If the supervisor mode is disabled, mask some general registers. */
736 if (visium_cpu_and_features
== PROCESSOR_GR5
)
738 fixed_regs
[24] = call_used_regs
[24] = 1;
739 fixed_regs
[25] = call_used_regs
[25] = 1;
740 fixed_regs
[26] = call_used_regs
[26] = 1;
741 fixed_regs
[27] = call_used_regs
[27] = 1;
742 fixed_regs
[28] = call_used_regs
[28] = 1;
743 call_really_used_regs
[24] = 0;
744 call_really_used_regs
[25] = 0;
745 call_really_used_regs
[26] = 0;
746 call_really_used_regs
[27] = 0;
747 call_really_used_regs
[28] = 0;
750 fixed_regs
[31] = call_used_regs
[31] = 1;
751 call_really_used_regs
[31] = 0;
753 /* We also need to change the long-branch register. */
754 if (visium_cpu_and_features
== PROCESSOR_GR5
)
755 long_branch_regnum
= 20;
757 long_branch_regnum
= 28;
760 /* If the FPU is disabled, mask the FP registers. */
763 for (int i
= FP_FIRST_REGNUM
; i
<= FP_LAST_REGNUM
; i
++)
765 fixed_regs
[i
] = call_used_regs
[i
] = 1;
766 call_really_used_regs
[i
] = 0;
771 /* Prepend to CLOBBERS hard registers that are automatically clobbered for
772 an asm We do this for the FLAGS to maintain source compatibility with
773 the original cc0-based compiler. */
776 visium_md_asm_adjust (vec
<rtx
> &/*outputs*/, vec
<rtx
> &/*inputs*/,
777 vec
<const char *> &/*constraints*/,
778 vec
<rtx
> &clobbers
, HARD_REG_SET
&clobbered_regs
)
780 clobbers
.safe_push (gen_rtx_REG (CCmode
, FLAGS_REGNUM
));
781 SET_HARD_REG_BIT (clobbered_regs
, FLAGS_REGNUM
);
785 /* Return true if X is a legitimate constant for a MODE immediate operand.
786 X is guaranteed to satisfy the CONSTANT_P predicate. */
789 visium_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED
,
790 rtx x ATTRIBUTE_UNUSED
)
795 /* Compute the alignment for a variable. The alignment of an aggregate is
796 set to be at least that of a scalar less than or equal to it in size. */
799 visium_data_alignment (tree type
, unsigned int align
)
801 if (AGGREGATE_TYPE_P (type
)
803 && TREE_CODE (TYPE_SIZE (type
)) == INTEGER_CST
&& align
< 32)
805 if (TREE_INT_CST_LOW (TYPE_SIZE (type
)) >= 32)
808 if (TREE_INT_CST_LOW (TYPE_SIZE (type
)) >= 16 && align
< 16)
815 /* Helper function for HARD_REGNO_RENAME_OK (FROM, TO). Return non-zero if
816 it is OK to rename a hard register FROM to another hard register TO. */
819 visium_hard_regno_rename_ok (unsigned int from ATTRIBUTE_UNUSED
,
822 /* If the function doesn't save LR, then the long-branch register will be
823 used for long branches so we need to know whether it is live before the
824 frame layout is computed. */
825 if (!current_function_saves_lr () && to
== long_branch_regnum
)
828 /* Interrupt functions can only use registers that have already been
829 saved by the prologue, even if they would normally be call-clobbered. */
831 && !df_regs_ever_live_p (to
)
832 && visium_interrupt_function_p ())
838 /* Return true if it is ok to do sibling call optimization for the specified
839 call expression EXP. DECL will be the called function, or NULL if this
840 is an indirect call. */
843 visium_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED
,
844 tree exp ATTRIBUTE_UNUSED
)
846 return !visium_interrupt_function_p ();
849 /* Prepare operands for a move define_expand in MODE. */
852 prepare_move_operands (rtx
*operands
, enum machine_mode mode
)
854 /* If the output is not a register, the input must be. */
855 if (GET_CODE (operands
[0]) == MEM
&& !reg_or_0_operand (operands
[1], mode
))
856 operands
[1] = force_reg (mode
, operands
[1]);
859 /* Return true if the operands are valid for a simple move insn. */
862 ok_for_simple_move_operands (rtx
*operands
, enum machine_mode mode
)
864 /* One of the operands must be a register. */
865 if (!register_operand (operands
[0], mode
)
866 && !reg_or_0_operand (operands
[1], mode
))
869 /* Once the flags are exposed, no simple moves between integer registers. */
870 if (visium_flags_exposed
871 && gpc_reg_operand (operands
[0], mode
)
872 && gpc_reg_operand (operands
[1], mode
))
878 /* Return true if the operands are valid for a simple move strict insn. */
881 ok_for_simple_move_strict_operands (rtx
*operands
, enum machine_mode mode
)
883 /* Once the flags are exposed, no simple moves between integer registers.
884 Note that, in QImode only, a zero source counts as an integer register
885 since it will be emitted as r0. */
886 if (visium_flags_exposed
887 && gpc_reg_operand (operands
[0], mode
)
888 && (gpc_reg_operand (operands
[1], mode
)
889 || (mode
== QImode
&& operands
[1] == const0_rtx
)))
895 /* Return true if the operands are valid for a simple arithmetic or logical
899 ok_for_simple_arith_logic_operands (rtx
*, enum machine_mode
)
901 /* Once the flags are exposed, no simple arithmetic or logical operations
902 between integer registers. */
903 return !visium_flags_exposed
;
906 /* Return non-zero if a branch or call instruction will be emitting a nop
907 into its delay slot. */
910 empty_delay_slot (rtx_insn
*insn
)
914 /* If no previous instruction (should not happen), return true. */
915 if (PREV_INSN (insn
) == NULL
)
918 seq
= NEXT_INSN (PREV_INSN (insn
));
919 if (GET_CODE (PATTERN (seq
)) == SEQUENCE
)
925 /* Wrapper around single_set which returns the first SET of a pair if the
926 second SET is to the flags register. */
929 single_set_and_flags (rtx_insn
*insn
)
931 if (multiple_sets (insn
))
933 rtx pat
= PATTERN (insn
);
934 if (XVECLEN (pat
, 0) == 2
935 && GET_CODE (XVECEXP (pat
, 0, 1)) == SET
936 && REG_P (SET_DEST (XVECEXP (pat
, 0, 1)))
937 && REGNO (SET_DEST (XVECEXP (pat
, 0, 1))) == FLAGS_REGNUM
)
938 return XVECEXP (pat
, 0, 0);
941 return single_set (insn
);
944 /* This is called with OUT_INSN an instruction setting a (base) register
945 and IN_INSN a read or a write. Return 1 if these instructions together
946 constitute a pipeline hazard.
948 On the original architecture, a pipeline data hazard occurs when the Dest
949 of one instruction becomes the SrcA for an immediately following READ or
950 WRITE instruction with a non-zero index (indexing occurs at the decode
951 stage and so a NOP must be inserted in-between for this to work).
958 On the MCM, the non-zero index condition is lifted but the hazard is
959 patched up by the hardware through the injection of wait states:
964 We nevertheless try to schedule instructions around this. */
967 gr5_hazard_bypass_p (rtx_insn
*out_insn
, rtx_insn
*in_insn
)
969 rtx out_set
, in_set
, dest
, memexpr
;
970 unsigned int out_reg
, in_reg
;
972 /* A CALL is storage register class, but the link register is of no
974 if (GET_CODE (out_insn
) == CALL_INSN
)
977 out_set
= single_set_and_flags (out_insn
);
978 dest
= SET_DEST (out_set
);
980 /* Should be no stall/hazard if OUT_INSN is MEM := ???. This only
981 occurs prior to reload. */
982 if (GET_CODE (dest
) == MEM
)
985 if (GET_CODE (dest
) == STRICT_LOW_PART
)
986 dest
= XEXP (dest
, 0);
987 if (GET_CODE (dest
) == SUBREG
)
988 dest
= SUBREG_REG (dest
);
989 out_reg
= REGNO (dest
);
991 in_set
= single_set_and_flags (in_insn
);
993 /* If IN_INSN is MEM := MEM, it's the source that counts. */
994 if (GET_CODE (SET_SRC (in_set
)) == MEM
)
995 memexpr
= XEXP (SET_SRC (in_set
), 0);
997 memexpr
= XEXP (SET_DEST (in_set
), 0);
999 if (GET_CODE (memexpr
) == PLUS
)
1001 memexpr
= XEXP (memexpr
, 0);
1002 if (GET_CODE (memexpr
) == SUBREG
)
1003 in_reg
= REGNO (SUBREG_REG (memexpr
));
1005 in_reg
= REGNO (memexpr
);
1007 if (in_reg
== out_reg
)
1010 else if (TARGET_MCM
)
1012 if (GET_CODE (memexpr
) == STRICT_LOW_PART
)
1013 memexpr
= XEXP (memexpr
, 0);
1014 if (GET_CODE (memexpr
) == SUBREG
)
1015 memexpr
= SUBREG_REG (memexpr
);
1016 in_reg
= REGNO (memexpr
);
1018 if (in_reg
== out_reg
)
1025 /* Return true if INSN is an empty asm instruction. */
1028 empty_asm_p (rtx insn
)
1030 rtx body
= PATTERN (insn
);
1033 if (GET_CODE (body
) == ASM_INPUT
)
1034 templ
= XSTR (body
, 0);
1035 else if (asm_noperands (body
) >= 0)
1036 templ
= decode_asm_operands (body
, NULL
, NULL
, NULL
, NULL
, NULL
);
1040 return (templ
&& templ
[0] == '\0');
1043 /* Insert a NOP immediately before INSN wherever there is a pipeline hazard.
1044 LAST_REG records the register set in the last insn and LAST_INSN_CALL
1045 records whether the last insn was a call insn. */
1048 gr5_avoid_hazard (rtx_insn
*insn
, unsigned int *last_reg
, bool *last_insn_call
)
1050 unsigned int dest_reg
= 0;
1053 switch (GET_CODE (insn
))
1057 *last_insn_call
= true;
1061 /* If this is an empty asm, just skip it. */
1062 if (!empty_asm_p (insn
))
1065 *last_insn_call
= false;
1070 /* If this is an empty asm, just skip it. */
1071 if (empty_asm_p (insn
))
1079 set
= single_set_and_flags (insn
);
1080 if (set
!= NULL_RTX
)
1082 rtx dest
= SET_DEST (set
);
1083 const bool double_p
= GET_MODE_SIZE (GET_MODE (dest
)) > UNITS_PER_WORD
;
1086 if (GET_CODE (SET_SRC (set
)) == MEM
)
1088 memrtx
= XEXP (SET_SRC (set
), 0);
1089 if (GET_CODE (dest
) == STRICT_LOW_PART
)
1090 dest
= XEXP (dest
, 0);
1092 dest_reg
= REGNO (dest
);
1094 /* If this is a DI or DF mode memory to register
1095 copy, then if rd = rs we get
1100 otherwise the order is
1107 unsigned int base_reg
;
1109 if (GET_CODE (memrtx
) == PLUS
)
1110 base_reg
= REGNO (XEXP (memrtx
, 0));
1112 base_reg
= REGNO (memrtx
);
1114 if (dest_reg
!= base_reg
)
1119 else if (GET_CODE (dest
) == MEM
)
1120 memrtx
= XEXP (dest
, 0);
1122 else if (GET_MODE_CLASS (GET_MODE (dest
)) != MODE_CC
)
1124 if (GET_CODE (dest
) == STRICT_LOW_PART
1125 ||GET_CODE (dest
) == ZERO_EXTRACT
)
1126 dest
= XEXP (dest
, 0);
1127 dest_reg
= REGNO (dest
);
1129 if (GET_CODE (SET_SRC (set
)) == REG
)
1131 unsigned int srcreg
= REGNO (SET_SRC (set
));
1133 /* Check for rs := rs, which will be deleted. */
1134 if (srcreg
== dest_reg
)
1137 /* In the case of a DI or DF mode move from register to
1138 register there is overlap if rd = rs + 1 in which case
1139 the order of the copies is reversed :
1144 if (double_p
&& dest_reg
!= srcreg
+ 1)
1149 /* If this is the delay slot of a call insn, any register it sets
1151 if (*last_insn_call
)
1154 /* If the previous insn sets the value of a register, and this insn
1155 uses a base register, check for the pipeline hazard where it is
1156 the same register in each case. */
1157 if (*last_reg
!= 0 && memrtx
!= NULL_RTX
)
1159 unsigned int reg
= 0;
1161 /* Check for an index (original architecture). */
1162 if (GET_CODE (memrtx
) == PLUS
)
1163 reg
= REGNO (XEXP (memrtx
, 0));
1165 /* Check for an MCM target or rs := [rs], in DI or DF mode. */
1166 else if (TARGET_MCM
|| (double_p
&& REGNO (memrtx
) == dest_reg
))
1167 reg
= REGNO (memrtx
);
1169 /* Remove any pipeline hazard by inserting a NOP. */
1170 if (reg
== *last_reg
)
1174 "inserting nop before insn %d\n", INSN_UID (insn
));
1175 emit_insn_after (gen_hazard_nop (), prev_active_insn (insn
));
1176 emit_insn_after (gen_blockage (), insn
);
1180 *last_reg
= dest_reg
;
1183 *last_insn_call
= false;
1186 /* Go through the instruction stream and insert nops where necessary to avoid
1187 pipeline hazards. There are two cases:
1189 1. On the original architecture, it is invalid to set the value of a
1190 (base) register and then use it in an address with a non-zero index
1191 in the next instruction.
1193 2. On the MCM, setting the value of a (base) register and then using
1194 it in address (including with zero index) in the next instruction
1195 will result in a pipeline stall of 3 cycles. */
1198 gr5_hazard_avoidance (void)
1200 unsigned int last_reg
= 0;
1201 bool last_insn_call
= false;
1204 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
1207 rtx pat
= PATTERN (insn
);
1209 if (GET_CODE (pat
) == SEQUENCE
)
1211 for (int i
= 0; i
< XVECLEN (pat
, 0); i
++)
1212 gr5_avoid_hazard (as_a
<rtx_insn
*> (XVECEXP (pat
, 0, i
)),
1213 &last_reg
, &last_insn_call
);
1216 else if (GET_CODE (insn
) == CALL_INSN
)
1218 /* This call is going to get a nop in its delay slot. */
1220 last_insn_call
= false;
1224 gr5_avoid_hazard (insn
, &last_reg
, &last_insn_call
);
1227 else if (GET_CODE (insn
) == BARRIER
)
1231 /* Perform a target-specific pass over the instruction stream. The compiler
1232 will run it at all optimization levels, just after the point at which it
1233 normally does delayed-branch scheduling. */
1238 if (visium_cpu
== PROCESSOR_GR5
)
1239 gr5_hazard_avoidance ();
1243 /* Return true if an argument must be passed by indirect reference. */
1246 visium_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED
,
1247 enum machine_mode mode ATTRIBUTE_UNUSED
,
1249 bool named ATTRIBUTE_UNUSED
)
1251 return type
&& (AGGREGATE_TYPE_P (type
) || TREE_CODE (type
) == VECTOR_TYPE
);
1254 /* Define how arguments are passed.
1256 A range of general registers and floating registers is available
1257 for passing arguments. When the class of registers which an
1258 argument would normally use is exhausted, that argument, is passed
1259 in the overflow region of the stack. No argument is split between
1260 registers and stack.
1262 Arguments of type float or _Complex float go in FP registers if FP
1263 hardware is available. If there is no FP hardware, arguments of
1264 type float go in general registers. All other arguments are passed
1265 in general registers. */
1268 visium_function_arg (cumulative_args_t pcum_v
, enum machine_mode mode
,
1269 const_tree type ATTRIBUTE_UNUSED
,
1270 bool named ATTRIBUTE_UNUSED
)
1273 CUMULATIVE_ARGS
*ca
= get_cumulative_args (pcum_v
);
1275 size
= (GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
1276 if (mode
== VOIDmode
)
1279 /* Scalar or complex single precision floating point arguments are returned
1280 in floating registers. */
1282 && ((GET_MODE_CLASS (mode
) == MODE_FLOAT
1283 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
)
1284 || (GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
1285 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
* 2)))
1287 if (ca
->frcount
+ size
<= MAX_ARGS_IN_FP_REGISTERS
)
1288 return gen_rtx_REG (mode
, FP_ARG_FIRST
+ ca
->frcount
);
1293 if (ca
->grcount
+ size
<= MAX_ARGS_IN_GP_REGISTERS
)
1294 return gen_rtx_REG (mode
, ca
->grcount
+ GP_ARG_FIRST
);
1299 /* Update the summarizer variable pointed to by PCUM_V to advance past an
1300 argument in the argument list. The values MODE, TYPE and NAMED describe
1301 that argument. Once this is done, the variable CUM is suitable for
1302 analyzing the _following_ argument with visium_function_arg. */
1305 visium_function_arg_advance (cumulative_args_t pcum_v
,
1306 enum machine_mode mode
,
1307 const_tree type ATTRIBUTE_UNUSED
,
1310 int size
= (GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
1312 CUMULATIVE_ARGS
*ca
= get_cumulative_args (pcum_v
);
1314 /* Scalar or complex single precision floating point arguments are returned
1315 in floating registers. */
1317 && ((GET_MODE_CLASS (mode
) == MODE_FLOAT
1318 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
)
1319 || (GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
1320 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
* 2)))
1322 if (ca
->frcount
+ size
<= MAX_ARGS_IN_FP_REGISTERS
)
1323 ca
->frcount
+= size
;
1327 ca
->frcount
= MAX_ARGS_IN_FP_REGISTERS
;
1332 /* Everything else goes in a general register, if enough are
1334 if (ca
->grcount
+ size
<= MAX_ARGS_IN_GP_REGISTERS
)
1335 ca
->grcount
+= size
;
1339 ca
->grcount
= MAX_ARGS_IN_GP_REGISTERS
;
1344 ca
->stack_words
+= stack_size
;
1347 /* Specify whether to return the return value in memory. */
1350 visium_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
1352 return (AGGREGATE_TYPE_P (type
) || TREE_CODE (type
) == VECTOR_TYPE
);
1355 /* Define how scalar values are returned. */
1358 visium_function_value_1 (enum machine_mode mode
)
1360 /* Scalar or complex single precision floating point values
1361 are returned in floating register f1. */
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)))
1367 return gen_rtx_REG (mode
, FP_RETURN_REGNUM
);
1369 /* All others are returned in r1. */
1370 return gen_rtx_REG (mode
, RETURN_REGNUM
);
1373 /* Return an RTX representing the place where a function returns or receives
1374 a value of data type RET_TYPE. */
1377 visium_function_value (const_tree ret_type
,
1378 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1379 bool outgoing ATTRIBUTE_UNUSED
)
1381 return visium_function_value_1 (TYPE_MODE (ret_type
));
1384 /* Return an RTX representing the place where the library function result will
1388 visium_libcall_value (enum machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
1390 return visium_function_value_1 (mode
);
1393 /* Store the anonymous register arguments into the stack so that all the
1394 arguments appear to have been passed consecutively on the stack. */
1397 visium_setup_incoming_varargs (cumulative_args_t pcum_v
,
1398 enum machine_mode mode
,
1400 int *pretend_size ATTRIBUTE_UNUSED
,
1403 cumulative_args_t local_args_so_far
;
1404 CUMULATIVE_ARGS local_copy
;
1405 CUMULATIVE_ARGS
*locargs
;
1406 int gp_saved
, fp_saved
, size
;
1408 /* Create an internal cumulative_args_t pointer to internally define
1409 storage to ensure calling TARGET_FUNCTION_ARG_ADVANCE does not
1410 make global changes. */
1411 local_args_so_far
.p
= &local_copy
;
1412 locargs
= get_cumulative_args (pcum_v
);
1415 local_args_so_far
.magic
= CUMULATIVE_ARGS_MAGIC
;
1418 local_copy
.grcount
= locargs
->grcount
;
1419 local_copy
.frcount
= locargs
->frcount
;
1420 local_copy
.stack_words
= locargs
->stack_words
;
1422 /* The caller has advanced ARGS_SO_FAR up to, but not beyond, the last named
1423 argument. Advance a local copy of ARGS_SO_FAR past the last "real" named
1424 argument, to find out how many registers are left over. */
1425 TARGET_FUNCTION_ARG_ADVANCE (local_args_so_far
, mode
, type
, 1);
1427 /* Find how many registers we need to save. */
1428 locargs
= get_cumulative_args (local_args_so_far
);
1429 gp_saved
= MAX_ARGS_IN_GP_REGISTERS
- locargs
->grcount
;
1430 fp_saved
= (TARGET_FPU
? MAX_ARGS_IN_FP_REGISTERS
- locargs
->frcount
: 0);
1431 size
= (gp_saved
* UNITS_PER_WORD
) + (fp_saved
* UNITS_PER_HWFPVALUE
);
1433 if (!no_rtl
&& size
> 0)
1435 /* To avoid negative offsets, which are not valid addressing modes on
1436 the Visium, we create a base register for the pretend args. */
1439 plus_constant (Pmode
, virtual_incoming_args_rtx
, -size
));
1444 = gen_rtx_MEM (BLKmode
,
1445 plus_constant (Pmode
,
1447 fp_saved
* UNITS_PER_HWFPVALUE
));
1448 MEM_NOTRAP_P (mem
) = 1;
1449 set_mem_alias_set (mem
, get_varargs_alias_set ());
1450 move_block_from_reg (locargs
->grcount
+ GP_ARG_FIRST
, mem
, gp_saved
);
1455 rtx mem
= gen_rtx_MEM (BLKmode
, ptr
);
1456 MEM_NOTRAP_P (mem
) = 1;
1457 set_mem_alias_set (mem
, get_varargs_alias_set ());
1458 gcc_assert (UNITS_PER_WORD
== UNITS_PER_HWFPVALUE
);
1459 move_block_from_reg (locargs
->frcount
+ FP_ARG_FIRST
, mem
, fp_saved
);
1463 visium_reg_parm_save_area_size
= size
;
1466 /* Define the `__builtin_va_list' type for the ABI. */
1469 visium_build_builtin_va_list (void)
1471 tree f_ovfl
, f_gbase
, f_fbase
, f_gbytes
, f_fbytes
, record
;
1473 record
= (*lang_hooks
.types
.make_type
) (RECORD_TYPE
);
1474 f_ovfl
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1475 get_identifier ("__overflow_argptr"), ptr_type_node
);
1476 f_gbase
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1477 get_identifier ("__gpr_base"), ptr_type_node
);
1478 f_fbase
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1479 get_identifier ("__fpr_base"), ptr_type_node
);
1480 f_gbytes
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1481 get_identifier ("__gpr_bytes"),
1482 short_unsigned_type_node
);
1483 f_fbytes
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1484 get_identifier ("__fpr_bytes"),
1485 short_unsigned_type_node
);
1487 DECL_FIELD_CONTEXT (f_ovfl
) = record
;
1488 DECL_FIELD_CONTEXT (f_gbase
) = record
;
1489 DECL_FIELD_CONTEXT (f_fbase
) = record
;
1490 DECL_FIELD_CONTEXT (f_gbytes
) = record
;
1491 DECL_FIELD_CONTEXT (f_fbytes
) = record
;
1492 TYPE_FIELDS (record
) = f_ovfl
;
1493 TREE_CHAIN (f_ovfl
) = f_gbase
;
1494 TREE_CHAIN (f_gbase
) = f_fbase
;
1495 TREE_CHAIN (f_fbase
) = f_gbytes
;
1496 TREE_CHAIN (f_gbytes
) = f_fbytes
;
1497 layout_type (record
);
1502 /* Implement `va_start' for varargs and stdarg. */
1505 visium_va_start (tree valist
, rtx nextarg ATTRIBUTE_UNUSED
)
1507 const CUMULATIVE_ARGS
*ca
= &crtl
->args
.info
;
1508 int gp_saved
= MAX_ARGS_IN_GP_REGISTERS
- ca
->grcount
;
1509 int fp_saved
= (TARGET_FPU
? MAX_ARGS_IN_FP_REGISTERS
- ca
->frcount
: 0);
1510 int named_stack_size
= ca
->stack_words
* UNITS_PER_WORD
, offset
;
1511 tree f_ovfl
, f_gbase
, f_fbase
, f_gbytes
, f_fbytes
;
1512 tree ovfl
, gbase
, gbytes
, fbase
, fbytes
, t
;
1514 f_ovfl
= TYPE_FIELDS (va_list_type_node
);
1515 f_gbase
= TREE_CHAIN (f_ovfl
);
1516 f_fbase
= TREE_CHAIN (f_gbase
);
1517 f_gbytes
= TREE_CHAIN (f_fbase
);
1518 f_fbytes
= TREE_CHAIN (f_gbytes
);
1519 ovfl
= build3 (COMPONENT_REF
, TREE_TYPE (f_ovfl
), valist
, f_ovfl
, NULL_TREE
);
1520 gbase
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbase
), valist
, f_gbase
,
1522 fbase
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbase
), valist
, f_fbase
,
1524 gbytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbytes
), valist
, f_gbytes
,
1526 fbytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbytes
), valist
, f_fbytes
,
1529 /* Store the stacked vararg pointer in the OVFL member. */
1530 t
= make_tree (TREE_TYPE (ovfl
), virtual_incoming_args_rtx
);
1531 t
= fold_build_pointer_plus_hwi (t
, named_stack_size
);
1532 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ovfl
), ovfl
, t
);
1533 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1535 /* Store the base address of the GPR save area into GBASE. */
1536 t
= make_tree (TREE_TYPE (gbase
), virtual_incoming_args_rtx
);
1537 offset
= MAX_ARGS_IN_GP_REGISTERS
* UNITS_PER_WORD
;
1538 t
= fold_build_pointer_plus_hwi (t
, -offset
);
1539 t
= build2 (MODIFY_EXPR
, TREE_TYPE (gbase
), gbase
, t
);
1540 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1542 /* Store the base address of the FPR save area into FBASE. */
1545 t
= make_tree (TREE_TYPE (fbase
), virtual_incoming_args_rtx
);
1546 offset
= gp_saved
* UNITS_PER_WORD
1547 + MAX_ARGS_IN_FP_REGISTERS
* UNITS_PER_HWFPVALUE
;
1548 t
= fold_build_pointer_plus_hwi (t
, -offset
);
1549 t
= build2 (MODIFY_EXPR
, TREE_TYPE (fbase
), fbase
, t
);
1550 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1553 /* Fill in the GBYTES member. */
1554 t
= build2 (MODIFY_EXPR
, TREE_TYPE (gbytes
), gbytes
,
1555 size_int (gp_saved
* UNITS_PER_WORD
));
1556 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1558 /* Fill in the FBYTES member. */
1559 t
= build2 (MODIFY_EXPR
, TREE_TYPE (fbytes
),
1560 fbytes
, size_int (fp_saved
* UNITS_PER_HWFPVALUE
));
1561 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1564 /* Implement `va_arg'. */
1567 visium_gimplify_va_arg (tree valist
, tree type
, gimple_seq
*pre_p
,
1570 tree f_ovfl
, f_gbase
, f_fbase
, f_gbytes
, f_fbytes
;
1571 tree ovfl
, base
, bytes
;
1572 HOST_WIDE_INT size
, rsize
;
1573 const bool by_reference_p
1574 = pass_by_reference (NULL
, TYPE_MODE (type
), type
, false);
1575 const bool float_reg_arg_p
1576 = (TARGET_FPU
&& !by_reference_p
1577 && ((GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
1578 && GET_MODE_SIZE (TYPE_MODE (type
)) <= UNITS_PER_HWFPVALUE
)
1579 || (GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_COMPLEX_FLOAT
1580 && (GET_MODE_SIZE (TYPE_MODE (type
))
1581 <= UNITS_PER_HWFPVALUE
* 2))));
1582 const int max_save_area_size
1583 = (float_reg_arg_p
? MAX_ARGS_IN_FP_REGISTERS
* UNITS_PER_HWFPVALUE
1584 : MAX_ARGS_IN_GP_REGISTERS
* UNITS_PER_WORD
);
1586 tree lab_false
, lab_over
, addr
;
1587 tree ptrtype
= build_pointer_type (type
);
1591 t
= visium_gimplify_va_arg (valist
, ptrtype
, pre_p
, post_p
);
1592 return build_va_arg_indirect_ref (t
);
1595 size
= int_size_in_bytes (type
);
1596 rsize
= (size
+ UNITS_PER_WORD
- 1) & -UNITS_PER_WORD
;
1597 f_ovfl
= TYPE_FIELDS (va_list_type_node
);
1598 f_gbase
= TREE_CHAIN (f_ovfl
);
1599 f_fbase
= TREE_CHAIN (f_gbase
);
1600 f_gbytes
= TREE_CHAIN (f_fbase
);
1601 f_fbytes
= TREE_CHAIN (f_gbytes
);
1603 /* We maintain separate pointers and offsets for floating-point and
1604 general registers, but we need similar code in both cases.
1608 BYTES be the number of unused bytes in the register save area.
1609 BASE be the base address of the register save area.
1610 OFFS be the current offset into the register save area. Either
1611 MAX_ARGS_IN_GP_REGISTERS * UNITS_PER_WORD - bytes or
1612 MAX_ARGS_IN_FP_REGISTERS * UNITS_PER_HWFPVALUE - bytes
1613 depending upon whether the argument is in general or floating
1615 ADDR_RTX be the address of the argument.
1616 RSIZE be the size in bytes of the argument.
1617 OVFL be the pointer to the stack overflow area.
1619 The code we want is:
1621 1: if (bytes >= rsize)
1623 3: addr_rtx = base + offs;
1635 addr
= create_tmp_var (ptr_type_node
, "addr");
1636 lab_false
= create_artificial_label (UNKNOWN_LOCATION
);
1637 lab_over
= create_artificial_label (UNKNOWN_LOCATION
);
1638 if (float_reg_arg_p
)
1639 bytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbytes
), unshare_expr (valist
),
1640 f_fbytes
, NULL_TREE
);
1642 bytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbytes
), unshare_expr (valist
),
1643 f_gbytes
, NULL_TREE
);
1645 /* [1] Emit code to branch if bytes < rsize. */
1646 t
= fold_convert (TREE_TYPE (bytes
), size_int (rsize
));
1647 t
= build2 (LT_EXPR
, boolean_type_node
, bytes
, t
);
1648 u
= build1 (GOTO_EXPR
, void_type_node
, lab_false
);
1649 t
= build3 (COND_EXPR
, void_type_node
, t
, u
, NULL_TREE
);
1650 gimplify_and_add (t
, pre_p
);
1652 /* [3] Emit code for: addr_rtx = base + offs, where
1653 offs = max_save_area_size - bytes. */
1654 t
= fold_convert (sizetype
, bytes
);
1655 offs
= build2 (MINUS_EXPR
, sizetype
, size_int (max_save_area_size
), t
);
1656 if (float_reg_arg_p
)
1657 base
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbase
), valist
, f_fbase
,
1660 base
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbase
), valist
, f_gbase
,
1663 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (base
), base
, offs
);
1664 t
= build2 (MODIFY_EXPR
, void_type_node
, addr
, t
);
1665 gimplify_and_add (t
, pre_p
);
1667 /* [4] Emit code for: bytes -= rsize. */
1668 t
= fold_convert (TREE_TYPE (bytes
), size_int (rsize
));
1669 t
= build2 (MINUS_EXPR
, TREE_TYPE (bytes
), bytes
, t
);
1670 t
= build2 (MODIFY_EXPR
, TREE_TYPE (bytes
), bytes
, t
);
1671 gimplify_and_add (t
, pre_p
);
1673 /* [6] Emit code to branch over the else clause, then the label. */
1674 t
= build1 (GOTO_EXPR
, void_type_node
, lab_over
);
1675 gimplify_and_add (t
, pre_p
);
1676 t
= build1 (LABEL_EXPR
, void_type_node
, lab_false
);
1677 gimplify_and_add (t
, pre_p
);
1679 /* [8] Emit code for: bytes = 0. */
1680 t
= fold_convert (TREE_TYPE (bytes
), size_int (0));
1681 t
= build2 (MODIFY_EXPR
, TREE_TYPE (bytes
), unshare_expr (bytes
), t
);
1682 gimplify_and_add (t
, pre_p
);
1684 /* [9] Emit code for: addr_rtx = ovfl. */
1685 ovfl
= build3 (COMPONENT_REF
, TREE_TYPE (f_ovfl
), valist
, f_ovfl
, NULL_TREE
);
1686 t
= build2 (MODIFY_EXPR
, void_type_node
, addr
, ovfl
);
1687 gimplify_and_add (t
, pre_p
);
1689 /* [10] Emit code for: ovfl += rsize. */
1690 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (ovfl
), ovfl
, size_int (rsize
));
1691 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ovfl
), unshare_expr (ovfl
), t
);
1692 gimplify_and_add (t
, pre_p
);
1693 t
= build1 (LABEL_EXPR
, void_type_node
, lab_over
);
1694 gimplify_and_add (t
, pre_p
);
1696 /* Emit a big-endian correction if size < UNITS_PER_WORD. */
1697 if (size
< UNITS_PER_WORD
)
1699 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (addr
), addr
,
1700 size_int (UNITS_PER_WORD
- size
));
1701 t
= build2 (MODIFY_EXPR
, void_type_node
, addr
, t
);
1702 gimplify_and_add (t
, pre_p
);
1705 addr
= fold_convert (ptrtype
, addr
);
1707 return build_va_arg_indirect_ref (addr
);
1710 /* Return true if OP is an offset suitable for use as a displacement in the
1711 address of a memory access in mode MODE. */
1714 rtx_ok_for_offset_p (enum machine_mode mode
, rtx op
)
1716 if (!CONST_INT_P (op
) || INTVAL (op
) < 0)
1722 return INTVAL (op
) <= 31;
1725 return (INTVAL (op
) % 2) == 0 && INTVAL (op
) < 63;
1729 return (INTVAL (op
) % 4) == 0 && INTVAL (op
) < 127;
1733 return (INTVAL (op
) % 4) == 0 && INTVAL (op
) < 123;
1740 /* Return whether X is a legitimate memory address for a memory operand
1743 Legitimate addresses are defined in two variants: a strict variant
1744 and a non-strict one. The STRICT parameter chooses which variant
1745 is desired by the caller.
1747 The strict variant is used in the reload pass. It must be defined
1748 so that any pseudo-register that has not been allocated a hard
1749 register is considered a memory reference. This is because in
1750 contexts where some kind of register is required, a
1751 pseudo-register with no hard register must be rejected. For
1752 non-hard registers, the strict variant should look up the
1753 `reg_renumber' array; it should then proceed using the hard
1754 register number in the array, or treat the pseudo as a memory
1755 reference if the array holds `-1'.
1757 The non-strict variant is used in other passes. It must be
1758 defined to accept all pseudo-registers in every context where some
1759 kind of register is required. */
1762 visium_legitimate_address_p (enum machine_mode mode
, rtx x
, bool strict
)
1767 /* If X is base+disp, check that we have an appropriate offset. */
1768 if (GET_CODE (x
) == PLUS
)
1770 if (!rtx_ok_for_offset_p (mode
, XEXP (x
, 1)))
1777 /* Now check the base: it must be either a register or a subreg thereof. */
1778 if (GET_CODE (base
) == SUBREG
)
1779 base
= SUBREG_REG (base
);
1783 regno
= REGNO (base
);
1785 /* For the strict variant, the register must be REGNO_OK_FOR_BASE_P. */
1787 return REGNO_OK_FOR_BASE_P (regno
);
1789 /* For the non-strict variant, the register may also be a pseudo. */
1790 return BASE_REGISTER_P (regno
) || regno
>= FIRST_PSEUDO_REGISTER
;
1793 /* Try machine-dependent ways of modifying an illegitimate address
1794 to be legitimate. If we find one, return the new, valid address.
1795 This macro is used in only one place: `memory_address' in explow.c.
1797 OLDX is the address as it was before break_out_memory_refs was called.
1798 In some cases it is useful to look at this to decide what needs to be done.
1800 MODE and WIN are passed so that this macro can use
1801 GO_IF_LEGITIMATE_ADDRESS.
1803 It is always safe for this macro to do nothing. It exists to recognize
1804 opportunities to optimize the output.
1808 memory (reg + <out of range int>)
1812 base_int = <out of range int> & ~mask
1813 ptr_reg = reg + base_int
1814 memory (ptr_reg + <out of range int> - base_int)
1816 Thus ptr_reg is a base register for a range of addresses,
1817 which should help CSE.
1819 For a 1 byte reference mask is 0x1f
1820 for a 2 byte reference mask is 0x3f
1821 For a 4 byte reference mask is 0x7f
1823 This reflects the indexing range of the processor.
1825 For a > 4 byte reference the mask is 0x7f provided all of the words
1826 can be accessed with the base address obtained. Otherwise a mask
1829 On rare occasions an unaligned base register value with an
1830 unaligned offset is generated. Unaligned offsets are left alone for
1834 visium_legitimize_address (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
1835 enum machine_mode mode
)
1837 if (GET_CODE (x
) == PLUS
1838 && GET_CODE (XEXP (x
, 1)) == CONST_INT
1839 && GET_CODE (XEXP (x
, 0)) == REG
&& mode
!= BLKmode
)
1841 int offset
= INTVAL (XEXP (x
, 1));
1842 int size
= GET_MODE_SIZE (mode
);
1843 int mask
= (size
== 1 ? 0x1f : (size
== 2 ? 0x3f : 0x7f));
1844 int mask1
= (size
== 1 ? 0 : (size
== 2 ? 1 : 3));
1845 int offset_base
= offset
& ~mask
;
1847 /* Check that all of the words can be accessed. */
1848 if (4 < size
&& 0x80 < size
+ offset
- offset_base
)
1849 offset_base
= offset
& ~0x3f;
1850 if (offset_base
!= 0 && offset_base
!= offset
&& (offset
& mask1
) == 0)
1852 rtx ptr_reg
= force_reg (Pmode
,
1853 gen_rtx_PLUS (Pmode
,
1855 GEN_INT (offset_base
)));
1857 return plus_constant (Pmode
, ptr_reg
, offset
- offset_base
);
1864 /* Perform a similar function to visium_legitimize_address, but this time
1865 for reload. Generating new registers is not an option here. Parts
1866 that need reloading are indicated by calling push_reload. */
1869 visium_legitimize_reload_address (rtx x
, enum machine_mode mode
, int opnum
,
1870 int type
, int ind ATTRIBUTE_UNUSED
)
1872 rtx newrtx
, tem
= NULL_RTX
;
1874 if (mode
== BLKmode
)
1877 if (optimize
&& GET_CODE (x
) == PLUS
)
1878 tem
= simplify_binary_operation (PLUS
, GET_MODE (x
), XEXP (x
, 0),
1881 newrtx
= tem
? tem
: x
;
1882 if (GET_CODE (newrtx
) == PLUS
1883 && GET_CODE (XEXP (newrtx
, 1)) == CONST_INT
1884 && GET_CODE (XEXP (newrtx
, 0)) == REG
1885 && BASE_REGISTER_P (REGNO (XEXP (newrtx
, 0))))
1887 int offset
= INTVAL (XEXP (newrtx
, 1));
1888 int size
= GET_MODE_SIZE (mode
);
1889 int mask
= (size
== 1 ? 0x1f : (size
== 2 ? 0x3f : 0x7f));
1890 int mask1
= (size
== 1 ? 0 : (size
== 2 ? 1 : 3));
1891 int offset_base
= offset
& ~mask
;
1893 /* Check that all of the words can be accessed. */
1894 if (4 < size
&& 0x80 < size
+ offset
- offset_base
)
1895 offset_base
= offset
& ~0x3f;
1897 if (offset_base
&& (offset
& mask1
) == 0)
1899 rtx temp
= gen_rtx_PLUS (Pmode
,
1900 XEXP (newrtx
, 0), GEN_INT (offset_base
));
1902 x
= gen_rtx_PLUS (Pmode
, temp
, GEN_INT (offset
- offset_base
));
1903 push_reload (XEXP (x
, 0), 0, &XEXP (x
, 0), 0,
1904 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
,
1905 (enum reload_type
) type
);
1913 /* Return the cost of moving data of mode MODE from a register in class FROM to
1914 one in class TO. A value of 2 is the default; other values are interpreted
1915 relative to that. */
1918 visium_register_move_cost (enum machine_mode mode
, reg_class_t from
,
1921 const int numwords
= (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
) ? 1 : 2;
1923 if (from
== MDB
|| to
== MDB
)
1925 else if (from
== MDC
|| to
== MDC
|| (from
== FP_REGS
) != (to
== FP_REGS
))
1926 return 4 * numwords
;
1928 return 2 * numwords
;
1931 /* Return the cost of moving data of mode MODE between a register of class
1932 CLASS and memory. IN is zero if the value is to be written to memory,
1933 non-zero if it is to be read in. This cost is relative to those in
1934 visium_register_move_cost. */
1937 visium_memory_move_cost (enum machine_mode mode
,
1938 reg_class_t to ATTRIBUTE_UNUSED
,
1941 /* Moving data in can be from PROM and this is expensive. */
1944 if (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
)
1950 /* Moving data out is mostly to RAM and should be cheaper. */
1953 if (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
)
1960 /* Return the relative costs of expression X. */
1963 visium_rtx_costs (rtx x
, machine_mode mode
, int outer_code ATTRIBUTE_UNUSED
,
1964 int opno ATTRIBUTE_UNUSED
, int *total
,
1965 bool speed ATTRIBUTE_UNUSED
)
1967 int code
= GET_CODE (x
);
1972 /* Small integers are as cheap as registers. 4-byte values can
1973 be fetched as immediate constants - let's give that the cost
1974 of an extra insn. */
1975 *total
= COSTS_N_INSNS (!satisfies_constraint_J (x
));
1981 *total
= COSTS_N_INSNS (2);
1987 split_double (x
, &high
, &low
);
1990 (!satisfies_constraint_J (high
) + !satisfies_constraint_J (low
));
1995 *total
= COSTS_N_INSNS (3);
2003 *total
= COSTS_N_INSNS (64);
2005 *total
= COSTS_N_INSNS (32);
2011 /* DImode operations are performed directly on the ALU. */
2013 *total
= COSTS_N_INSNS (2);
2015 *total
= COSTS_N_INSNS (1);
2021 /* DImode operations are performed on the EAM instead. */
2023 *total
= COSTS_N_INSNS (3);
2025 *total
= COSTS_N_INSNS (1);
2029 /* This matches the btst pattern. */
2030 if (GET_CODE (XEXP (x
, 0)) == ZERO_EXTRACT
2031 && XEXP (x
, 1) == const0_rtx
2032 && XEXP (XEXP (x
, 0), 1) == const1_rtx
2033 && satisfies_constraint_K (XEXP (XEXP (x
, 0), 2)))
2034 *total
= COSTS_N_INSNS (1);
2042 /* Split a double move of OPERANDS in MODE. */
2045 visium_split_double_move (rtx
*operands
, enum machine_mode mode
)
2049 /* Check register to register with overlap. */
2050 if (GET_CODE (operands
[0]) == REG
2051 && GET_CODE (operands
[1]) == REG
2052 && REGNO (operands
[0]) == REGNO (operands
[1]) + 1)
2055 /* Check memory to register where the base reg overlaps the destination. */
2056 if (GET_CODE (operands
[0]) == REG
&& GET_CODE (operands
[1]) == MEM
)
2058 rtx op
= XEXP (operands
[1], 0);
2060 if (GET_CODE (op
) == SUBREG
)
2061 op
= SUBREG_REG (op
);
2063 if (GET_CODE (op
) == REG
&& REGNO (op
) == REGNO (operands
[0]))
2066 if (GET_CODE (op
) == PLUS
)
2068 rtx x
= XEXP (op
, 0);
2069 rtx y
= XEXP (op
, 1);
2071 if (GET_CODE (x
) == REG
&& REGNO (x
) == REGNO (operands
[0]))
2074 if (GET_CODE (y
) == REG
&& REGNO (y
) == REGNO (operands
[0]))
2081 operands
[2] = operand_subword (operands
[0], 1, 1, mode
);
2082 operands
[3] = operand_subword (operands
[1], 1, 1, mode
);
2083 operands
[4] = operand_subword (operands
[0], 0, 1, mode
);
2084 operands
[5] = operand_subword (operands
[1], 0, 1, mode
);
2088 operands
[2] = operand_subword (operands
[0], 0, 1, mode
);
2089 operands
[3] = operand_subword (operands
[1], 0, 1, mode
);
2090 operands
[4] = operand_subword (operands
[0], 1, 1, mode
);
2091 operands
[5] = operand_subword (operands
[1], 1, 1, mode
);
2095 /* Split a double addition or subtraction of operands. */
2098 visium_split_double_add (enum rtx_code code
, rtx op0
, rtx op1
, rtx op2
)
2100 rtx op3
= gen_lowpart (SImode
, op0
);
2101 rtx op4
= gen_lowpart (SImode
, op1
);
2103 rtx op6
= gen_highpart (SImode
, op0
);
2104 rtx op7
= (op1
== const0_rtx
? op1
: gen_highpart (SImode
, op1
));
2108 /* If operand #2 is a small constant, then its high part is null. */
2109 if (CONST_INT_P (op2
))
2111 HOST_WIDE_INT val
= INTVAL (op2
);
2115 code
= (code
== MINUS
? PLUS
: MINUS
);
2119 op5
= gen_int_mode (val
, SImode
);
2124 op5
= gen_lowpart (SImode
, op2
);
2125 op8
= gen_highpart (SImode
, op2
);
2128 if (op4
== const0_rtx
)
2129 pat
= gen_negsi2_insn_set_carry (op3
, op5
);
2130 else if (code
== MINUS
)
2131 pat
= gen_subsi3_insn_set_carry (op3
, op4
, op5
);
2133 pat
= gen_addsi3_insn_set_carry (op3
, op4
, op5
);
2136 /* This is the plus_[plus_]sltu_flags or minus_[minus_]sltu_flags pattern. */
2137 if (op8
== const0_rtx
)
2140 x
= gen_rtx_fmt_ee (code
, SImode
, op7
, op8
);
2141 flags
= gen_rtx_REG (CCCmode
, FLAGS_REGNUM
);
2142 x
= gen_rtx_fmt_ee (code
, SImode
, x
, gen_rtx_LTU (SImode
, flags
, const0_rtx
));
2143 pat
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (2));
2144 XVECEXP (pat
, 0, 0) = gen_rtx_SET (op6
, x
);
2145 flags
= gen_rtx_REG (CCmode
, FLAGS_REGNUM
);
2146 XVECEXP (pat
, 0, 1) = gen_rtx_CLOBBER (VOIDmode
, flags
);
2149 visium_flags_exposed
= true;
2152 /* Expand a copysign of OPERANDS in MODE. */
2155 visium_expand_copysign (rtx
*operands
, enum machine_mode mode
)
2157 rtx op0
= operands
[0];
2158 rtx op1
= operands
[1];
2159 rtx op2
= operands
[2];
2160 rtx mask
= force_reg (SImode
, GEN_INT (0x7fffffff));
2163 /* We manually handle SFmode because the abs and neg instructions of
2164 the FPU on the MCM have a non-standard behavior wrt NaNs. */
2165 gcc_assert (mode
== SFmode
);
2167 /* First get all the non-sign bits of op1. */
2168 if (GET_CODE (op1
) == CONST_DOUBLE
)
2170 if (real_isneg (CONST_DOUBLE_REAL_VALUE (op1
)))
2171 op1
= simplify_unary_operation (ABS
, mode
, op1
, mode
);
2172 if (op1
!= CONST0_RTX (mode
))
2175 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op1
), l
);
2176 op1
= force_reg (SImode
, gen_int_mode (l
, SImode
));
2181 op1
= copy_to_mode_reg (SImode
, gen_lowpart (SImode
, op1
));
2182 op1
= force_reg (SImode
, gen_rtx_AND (SImode
, op1
, mask
));
2185 /* Then get the sign bit of op2. */
2186 mask
= force_reg (SImode
, gen_rtx_NOT (SImode
, mask
));
2187 op2
= copy_to_mode_reg (SImode
, gen_lowpart (SImode
, op2
));
2188 op2
= force_reg (SImode
, gen_rtx_AND (SImode
, op2
, mask
));
2190 /* Finally OR the two values. */
2191 if (op1
== CONST0_RTX (SFmode
))
2194 x
= force_reg (SImode
, gen_rtx_IOR (SImode
, op1
, op2
));
2196 /* And move the result to the destination. */
2197 emit_insn (gen_rtx_SET (op0
, gen_lowpart (SFmode
, x
)));
2200 /* Expand a cstore of OPERANDS in MODE for EQ/NE/LTU/GTU/GEU/LEU. We generate
2201 the result in the C flag and use the ADC/SUBC instructions to write it into
2202 the destination register.
2204 It would also be possible to implement support for LT/GT/LE/GE by means of
2205 the RFLAG instruction followed by some shifts, but this can pessimize the
2209 visium_expand_int_cstore (rtx
*operands
, enum machine_mode mode
)
2211 enum rtx_code code
= GET_CODE (operands
[1]);
2212 rtx op0
= operands
[0], op1
= operands
[2], op2
= operands
[3], sltu
;
2213 bool reverse
= false;
2219 /* We use a special comparison to get the result in the C flag. */
2220 if (op2
!= const0_rtx
)
2221 op1
= force_reg (mode
, gen_rtx_XOR (mode
, op1
, op2
));
2222 op1
= gen_rtx_NOT (mode
, op1
);
2230 /* The result is naturally in the C flag modulo a couple of tricks. */
2231 code
= reverse_condition (code
);
2234 /* ... fall through ... */
2250 /* We need either a single ADC or a SUBC and a PLUS. */
2251 sltu
= gen_rtx_LTU (SImode
, op1
, op2
);
2255 rtx tmp
= copy_to_mode_reg (SImode
, gen_rtx_NEG (SImode
, sltu
));
2256 emit_insn (gen_add3_insn (op0
, tmp
, const1_rtx
));
2259 emit_insn (gen_rtx_SET (op0
, sltu
));
2262 /* Expand a cstore of OPERANDS in MODE for LT/GT/UNGE/UNLE. We generate the
2263 result in the C flag and use the ADC/SUBC instructions to write it into
2264 the destination register. */
2267 visium_expand_fp_cstore (rtx
*operands
,
2268 enum machine_mode mode ATTRIBUTE_UNUSED
)
2270 enum rtx_code code
= GET_CODE (operands
[1]);
2271 rtx op0
= operands
[0], op1
= operands
[2], op2
= operands
[3], slt
;
2272 bool reverse
= false;
2278 /* The result is naturally in the C flag modulo a couple of tricks. */
2279 code
= reverse_condition_maybe_unordered (code
);
2282 /* ... fall through ... */
2298 /* We need either a single ADC or a SUBC and a PLUS. */
2299 slt
= gen_rtx_LT (SImode
, op1
, op2
);
2303 rtx tmp
= copy_to_mode_reg (SImode
, gen_rtx_NEG (SImode
, slt
));
2304 emit_insn (gen_add3_insn (op0
, tmp
, const1_rtx
));
2307 emit_insn (gen_rtx_SET (op0
, slt
));
2310 /* Split a compare-and-store with CODE, operands OP2 and OP3, combined with
2311 operation with OP_CODE, operands OP0 and OP1. */
2314 visium_split_cstore (enum rtx_code op_code
, rtx op0
, rtx op1
,
2315 enum rtx_code code
, rtx op2
, rtx op3
)
2317 enum machine_mode cc_mode
= visium_select_cc_mode (code
, op2
, op3
);
2319 /* If a FP cstore was reversed, then it was originally UNGE/UNLE. */
2320 if (cc_mode
== CCFPEmode
&& (op_code
== NEG
|| op_code
== MINUS
))
2323 rtx flags
= gen_rtx_REG (cc_mode
, FLAGS_REGNUM
);
2324 rtx x
= gen_rtx_COMPARE (cc_mode
, op2
, op3
);
2325 x
= gen_rtx_SET (flags
, x
);
2328 x
= gen_rtx_fmt_ee (code
, SImode
, flags
, const0_rtx
);
2334 x
= gen_rtx_NEG (SImode
, x
);
2338 x
= gen_rtx_fmt_ee (op_code
, SImode
, op1
, x
);
2344 rtx pat
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (2));
2345 XVECEXP (pat
, 0, 0) = gen_rtx_SET (op0
, x
);
2346 flags
= gen_rtx_REG (CCmode
, FLAGS_REGNUM
);
2347 XVECEXP (pat
, 0, 1) = gen_rtx_CLOBBER (VOIDmode
, flags
);
2350 visium_flags_exposed
= true;
2353 /* Generate a call to a library function to move BYTES_RTX bytes from SRC with
2354 address SRC_REG to DST with address DST_REG in 4-byte chunks. */
2357 expand_block_move_4 (rtx dst
, rtx dst_reg
, rtx src
, rtx src_reg
, rtx bytes_rtx
)
2359 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2360 unsigned int rem
= bytes
% 4;
2367 emit_move_insn (regno_reg_rtx
[1], dst_reg
);
2368 emit_move_insn (regno_reg_rtx
[2], src_reg
);
2369 emit_move_insn (regno_reg_rtx
[3], bytes_rtx
);
2371 insn
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (8));
2372 XVECEXP (insn
, 0, 0)
2373 = gen_rtx_SET (replace_equiv_address_nv (dst
, regno_reg_rtx
[1]),
2374 replace_equiv_address_nv (src
, regno_reg_rtx
[2]));
2375 XVECEXP (insn
, 0, 1) = gen_rtx_USE (VOIDmode
, regno_reg_rtx
[3]);
2376 for (i
= 1; i
<= 6; i
++)
2377 XVECEXP (insn
, 0, 1 + i
)
2378 = gen_rtx_CLOBBER (VOIDmode
, regno_reg_rtx
[i
]);
2382 emit_library_call (long_int_memcpy_libfunc
, LCT_NORMAL
, VOIDmode
, 3,
2385 convert_to_mode (TYPE_MODE (sizetype
),
2386 GEN_INT (bytes
>> 2),
2387 TYPE_UNSIGNED (sizetype
)),
2388 TYPE_MODE (sizetype
));
2392 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2393 src
= replace_equiv_address_nv (src
, src_reg
);
2398 emit_move_insn (adjust_address_nv (dst
, HImode
, bytes
),
2399 adjust_address_nv (src
, HImode
, bytes
));
2405 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2406 adjust_address_nv (src
, QImode
, bytes
));
2409 /* Generate a call to a library function to move BYTES_RTX bytes from SRC with
2410 address SRC_REG to DST with address DST_REG in 2-bytes chunks. */
2413 expand_block_move_2 (rtx dst
, rtx dst_reg
, rtx src
, rtx src_reg
, rtx bytes_rtx
)
2415 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2416 unsigned int rem
= bytes
% 2;
2418 emit_library_call (wrd_memcpy_libfunc
, LCT_NORMAL
, VOIDmode
, 3,
2421 convert_to_mode (TYPE_MODE (sizetype
),
2422 GEN_INT (bytes
>> 1),
2423 TYPE_UNSIGNED (sizetype
)),
2424 TYPE_MODE (sizetype
));
2428 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2429 src
= replace_equiv_address_nv (src
, src_reg
);
2432 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2433 adjust_address_nv (src
, QImode
, bytes
));
2436 /* Generate a call to a library function to move BYTES_RTX bytes from address
2437 SRC_REG to address DST_REG in 1-byte chunks. */
2440 expand_block_move_1 (rtx dst_reg
, rtx src_reg
, rtx bytes_rtx
)
2442 emit_library_call (byt_memcpy_libfunc
, LCT_NORMAL
, VOIDmode
, 3,
2445 convert_to_mode (TYPE_MODE (sizetype
),
2447 TYPE_UNSIGNED (sizetype
)),
2448 TYPE_MODE (sizetype
));
2451 /* Generate a call to a library function to set BYTES_RTX bytes of DST with
2452 address DST_REG to VALUE_RTX in 4-byte chunks. */
2455 expand_block_set_4 (rtx dst
, rtx dst_reg
, rtx value_rtx
, rtx bytes_rtx
)
2457 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2458 unsigned int rem
= bytes
% 4;
2460 value_rtx
= convert_to_mode (Pmode
, value_rtx
, 1);
2461 emit_library_call (long_int_memset_libfunc
, LCT_NORMAL
, VOIDmode
, 3,
2464 convert_to_mode (TYPE_MODE (sizetype
),
2465 GEN_INT (bytes
>> 2),
2466 TYPE_UNSIGNED (sizetype
)),
2467 TYPE_MODE (sizetype
));
2471 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2476 if (CONST_INT_P (value_rtx
))
2478 const unsigned HOST_WIDE_INT value
= UINTVAL (value_rtx
) & 0xff;
2479 emit_move_insn (adjust_address_nv (dst
, HImode
, bytes
),
2480 gen_int_mode ((value
<< 8) | value
, HImode
));
2484 rtx temp
= convert_to_mode (QImode
, value_rtx
, 1);
2485 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
), temp
);
2486 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
+ 1), temp
);
2493 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2494 convert_to_mode (QImode
, value_rtx
, 1));
2497 /* Generate a call to a library function to set BYTES_RTX bytes of DST with
2498 address DST_REG to VALUE_RTX in 2-byte chunks. */
2501 expand_block_set_2 (rtx dst
, rtx dst_reg
, rtx value_rtx
, rtx bytes_rtx
)
2503 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2504 unsigned int rem
= bytes
% 2;
2506 value_rtx
= convert_to_mode (Pmode
, value_rtx
, 1);
2507 emit_library_call (wrd_memset_libfunc
, LCT_NORMAL
, VOIDmode
, 3,
2510 convert_to_mode (TYPE_MODE (sizetype
),
2511 GEN_INT (bytes
>> 1),
2512 TYPE_UNSIGNED (sizetype
)),
2513 TYPE_MODE (sizetype
));
2517 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2520 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2521 convert_to_mode (QImode
, value_rtx
, 1));
2524 /* Generate a call to a library function to set BYTES_RTX bytes at address
2525 DST_REG to VALUE_RTX in 1-byte chunks. */
2528 expand_block_set_1 (rtx dst_reg
, rtx value_rtx
, rtx bytes_rtx
)
2530 value_rtx
= convert_to_mode (Pmode
, value_rtx
, 1);
2531 emit_library_call (byt_memset_libfunc
, LCT_NORMAL
, VOIDmode
, 3,
2534 convert_to_mode (TYPE_MODE (sizetype
),
2536 TYPE_UNSIGNED (sizetype
)),
2537 TYPE_MODE (sizetype
));
2540 /* Expand string/block move operations.
2542 operands[0] is the pointer to the destination.
2543 operands[1] is the pointer to the source.
2544 operands[2] is the number of bytes to move.
2545 operands[3] is the alignment.
2547 Return 1 upon success, 0 otherwise. */
2550 visium_expand_block_move (rtx
*operands
)
2552 rtx dst
= operands
[0];
2553 rtx src
= operands
[1];
2554 rtx bytes_rtx
= operands
[2];
2555 rtx align_rtx
= operands
[3];
2556 const int align
= INTVAL (align_rtx
);
2557 rtx dst_reg
, src_reg
;
2558 tree dst_expr
, src_expr
;
2560 /* We only handle a fixed number of bytes for now. */
2561 if (!CONST_INT_P (bytes_rtx
) || INTVAL (bytes_rtx
) <= 0)
2564 /* Copy the addresses into scratch registers. */
2565 dst_reg
= copy_addr_to_reg (XEXP (dst
, 0));
2566 src_reg
= copy_addr_to_reg (XEXP (src
, 0));
2568 /* Move the data with the appropriate granularity. */
2570 expand_block_move_4 (dst
, dst_reg
, src
, src_reg
, bytes_rtx
);
2571 else if (align
>= 2)
2572 expand_block_move_2 (dst
, dst_reg
, src
, src_reg
, bytes_rtx
);
2574 expand_block_move_1 (dst_reg
, src_reg
, bytes_rtx
);
2576 /* Since DST and SRC are passed to a libcall, mark the corresponding
2577 tree EXPR as addressable. */
2578 dst_expr
= MEM_EXPR (dst
);
2579 src_expr
= MEM_EXPR (src
);
2581 mark_addressable (dst_expr
);
2583 mark_addressable (src_expr
);
2588 /* Expand string/block set operations.
2590 operands[0] is the pointer to the destination.
2591 operands[1] is the number of bytes to set.
2592 operands[2] is the source value.
2593 operands[3] is the alignment.
2595 Return 1 upon success, 0 otherwise. */
2598 visium_expand_block_set (rtx
*operands
)
2600 rtx dst
= operands
[0];
2601 rtx bytes_rtx
= operands
[1];
2602 rtx value_rtx
= operands
[2];
2603 rtx align_rtx
= operands
[3];
2604 const int align
= INTVAL (align_rtx
);
2608 /* We only handle a fixed number of bytes for now. */
2609 if (!CONST_INT_P (bytes_rtx
) || INTVAL (bytes_rtx
) <= 0)
2612 /* Copy the address into a scratch register. */
2613 dst_reg
= copy_addr_to_reg (XEXP (dst
, 0));
2615 /* Set the data with the appropriate granularity. */
2617 expand_block_set_4 (dst
, dst_reg
, value_rtx
, bytes_rtx
);
2618 else if (align
>= 2)
2619 expand_block_set_2 (dst
, dst_reg
, value_rtx
, bytes_rtx
);
2621 expand_block_set_1 (dst_reg
, value_rtx
, bytes_rtx
);
2623 /* Since DST is passed to a libcall, mark the corresponding
2624 tree EXPR as addressable. */
2625 dst_expr
= MEM_EXPR (dst
);
2627 mark_addressable (dst_expr
);
2632 /* Initialize a trampoline. M_TRAMP is an RTX for the memory block for the
2633 trampoline, FNDECL is the FUNCTION_DECL for the nested function and
2634 STATIC_CHAIN is an RTX for the static chain value that should be passed
2635 to the function when it is called. */
2638 visium_trampoline_init (rtx m_tramp
, tree fndecl
, rtx static_chain
)
2640 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2641 rtx addr
= XEXP (m_tramp
, 0);
2643 /* The trampoline initialization sequence is:
2645 moviu r9,%u FUNCTION
2646 movil r9,%l FUNCTION
2651 We don't use r0 as the destination register of the branch because we want
2652 the Branch Pre-decode Logic of the GR6 to use the Address Load Array to
2653 predict the branch target. */
2655 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 0)),
2656 plus_constant (SImode
,
2657 expand_shift (RSHIFT_EXPR
, SImode
, fnaddr
,
2661 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 4)),
2662 plus_constant (SImode
,
2663 expand_and (SImode
, fnaddr
, GEN_INT (0xffff),
2667 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 8)),
2668 plus_constant (SImode
,
2669 expand_shift (RSHIFT_EXPR
, SImode
,
2674 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 12)),
2675 gen_int_mode (0xff892404, SImode
));
2677 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 16)),
2678 plus_constant (SImode
,
2679 expand_and (SImode
, static_chain
,
2680 GEN_INT (0xffff), NULL_RTX
),
2683 emit_library_call (set_trampoline_parity_libfunc
, LCT_NORMAL
, VOIDmode
, 1,
2687 /* Return true if the current function must have and use a frame pointer. */
2690 visium_frame_pointer_required (void)
2692 /* The frame pointer is required if the function isn't leaf to be able to
2693 do manual stack unwinding. */
2697 /* If the stack pointer is dynamically modified in the function, it cannot
2698 serve as the frame pointer. */
2699 if (!crtl
->sp_is_unchanging
)
2702 /* If the function receives nonlocal gotos, it needs to save the frame
2703 pointer in the nonlocal_goto_save_area object. */
2704 if (cfun
->has_nonlocal_label
)
2707 /* The frame also needs to be established in some special cases. */
2708 if (visium_frame_needed
)
2714 /* Profiling support. Just a call to MCOUNT is needed. No labelled counter
2715 location is involved. Proper support for __builtin_return_address is also
2716 required, which is fairly straightforward provided a frame gets created. */
2719 visium_profile_hook (void)
2721 visium_frame_needed
= true;
2722 emit_library_call (gen_rtx_SYMBOL_REF (Pmode
, "mcount"), LCT_NORMAL
,
2726 /* A C expression whose value is RTL representing the address in a stack frame
2727 where the pointer to the caller's frame is stored. Assume that FRAMEADDR is
2728 an RTL expression for the address of the stack frame itself.
2730 If you don't define this macro, the default is to return the value of
2731 FRAMEADDR--that is, the stack frame address is also the address of the stack
2732 word that points to the previous frame. */
2735 visium_dynamic_chain_address (rtx frame
)
2737 /* This is the default, but we need to make sure the frame gets created. */
2738 visium_frame_needed
= true;
2742 /* A C expression whose value is RTL representing the value of the return
2743 address for the frame COUNT steps up from the current frame, after the
2744 prologue. FRAMEADDR is the frame pointer of the COUNT frame, or the frame
2745 pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' is
2748 The value of the expression must always be the correct address when COUNT is
2749 zero, but may be `NULL_RTX' if there is not way to determine the return
2750 address of other frames. */
2753 visium_return_addr_rtx (int count
, rtx frame ATTRIBUTE_UNUSED
)
2755 /* Dont try to compute anything other than frame zero. */
2759 visium_frame_needed
= true;
2761 gen_frame_mem (Pmode
, plus_constant (Pmode
, hard_frame_pointer_rtx
, 4));
2764 /* Helper function for EH_RETURN_HANDLER_RTX. Return the RTX representing a
2765 location in which to store the address of an exception handler to which we
2769 visium_eh_return_handler_rtx (void)
2772 = gen_frame_mem (SImode
, plus_constant (Pmode
, hard_frame_pointer_rtx
, 4));
2773 MEM_VOLATILE_P (mem
) = 1;
2777 static struct machine_function
*
2778 visium_init_machine_status (void)
2780 return ggc_cleared_alloc
<machine_function
> ();
2783 /* The per-function data machinery is needed to indicate when a frame
2787 visium_init_expanders (void)
2789 init_machine_status
= visium_init_machine_status
;
2792 /* Given a comparison code (EQ, NE, etc.) and the operands of a COMPARE,
2793 return the mode to be used for the comparison. */
2796 visium_select_cc_mode (enum rtx_code code
, rtx op0
, rtx op1
)
2798 if (GET_MODE_CLASS (GET_MODE (op0
)) == MODE_FLOAT
)
2818 /* These 2 comparison codes are not supported. */
2826 /* This is for the cmp<mode>_sne pattern. */
2827 if (op1
== constm1_rtx
)
2830 /* This is for the add<mode>3_insn_set_carry pattern. */
2831 if ((code
== LTU
|| code
== GEU
)
2832 && GET_CODE (op0
) == PLUS
2833 && rtx_equal_p (XEXP (op0
, 0), op1
))
2836 if (op1
!= const0_rtx
)
2839 switch (GET_CODE (op0
))
2847 /* The C and V flags may be set differently from a COMPARE with zero.
2848 The consequence is that a comparison operator testing C or V must
2849 be turned into another operator not testing C or V and yielding
2850 the same result for a comparison with zero. That's possible for
2851 GE/LT which become NC/NS respectively, but not for GT/LE for which
2852 the altered operator doesn't exist on the Visium. */
2856 /* This is a btst, the result is in C instead of Z. */
2860 /* This is a degenerate case, typically an uninitialized variable. */
2861 gcc_assert (op0
== constm1_rtx
);
2863 /* ... fall through ... */
2874 /* Pretend that the flags are set as for a COMPARE with zero.
2875 That's mostly true, except for the 2 right shift insns that
2876 will set the C flag. But the C flag is relevant only for
2877 the unsigned comparison operators and they are eliminated
2878 when applied to a comparison with zero. */
2886 /* Split a compare-and-branch with CODE, operands OP0 and OP1, and LABEL. */
2889 visium_split_cbranch (enum rtx_code code
, rtx op0
, rtx op1
, rtx label
)
2891 enum machine_mode cc_mode
= visium_select_cc_mode (code
, op0
, op1
);
2892 rtx flags
= gen_rtx_REG (cc_mode
, FLAGS_REGNUM
);
2894 rtx x
= gen_rtx_COMPARE (cc_mode
, op0
, op1
);
2895 x
= gen_rtx_SET (flags
, x
);
2898 x
= gen_rtx_fmt_ee (code
, VOIDmode
, flags
, const0_rtx
);
2899 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
, gen_rtx_LABEL_REF (Pmode
, label
),
2901 x
= gen_rtx_SET (pc_rtx
, x
);
2904 visium_flags_exposed
= true;
2907 /* Branch instructions on the Visium.
2909 Setting aside the interrupt-handling specific instructions, the ISA has
2910 two branch instructions: BRR and BRA. The former is used to implement
2911 short branches (+/- 2^17) within functions and its target is encoded in
2912 the instruction. The latter is used to implement all the other types
2913 of control flow changes and its target might not be statically known
2914 or even easily predictable at run time. Here's a complete summary of
2915 the patterns that generate a BRA instruction:
2925 Among these patterns, only the return (5) and the long branch (6) can be
2926 conditional; all the other patterns are always unconditional.
2928 The following algorithm can be used to identify the pattern for which
2929 the BRA instruction was generated and work out its target:
2931 A. If the source is r21 and the destination is r0, this is a return (5)
2932 and the target is the caller (i.e. the value of r21 on function's
2935 B. If the source is rN, N != 21 and the destination is r0, this is either
2936 an indirect jump or a table jump (1, 2) and the target is not easily
2939 C. If the source is rN, N != 21 and the destination is r21, this is a call
2940 (3) and the target is given by the preceding MOVIL/MOVIU pair for rN,
2941 unless this is an indirect call in which case the target is not easily
2944 D. If the source is rN, N != 21 and the destination is also rN, this is
2945 either a sibling call or a trampoline (4, 7) and the target is given
2946 by the preceding MOVIL/MOVIU pair for rN.
2948 E. If the source is r21 and the destination is also r21, this is a long
2949 branch (6) and the target is given by the preceding MOVIL/MOVIU pair
2952 The other combinations are not used. This implementation has been devised
2953 to accommodate the branch predictor of the GR6 but is used unconditionally
2954 by the compiler, i.e. including for earlier processors. */
2956 /* Output a conditional/unconditional branch to LABEL. COND is the string
2957 condition. INSN is the instruction. */
2960 output_branch (rtx label
, const char *cond
, rtx_insn
*insn
)
2966 operands
[0] = label
;
2968 /* If the length of the instruction is greater than 8, then this is a
2969 long branch and we need to work harder to emit it properly. */
2970 if (get_attr_length (insn
) > 8)
2974 /* If the link register has been saved, then we use it. */
2975 if (current_function_saves_lr ())
2977 operands
[1] = regno_reg_rtx
[LINK_REGNUM
];
2981 /* Or else, if the long-branch register isn't live, we use it. */
2982 else if (!df_regs_ever_live_p (long_branch_regnum
))
2984 operands
[1] = regno_reg_rtx
[long_branch_regnum
];
2988 /* Otherwise, we will use the long-branch register but we need to
2989 spill it to the stack and reload it at the end. We should have
2990 reserved the LR slot for this purpose. */
2993 operands
[1] = regno_reg_rtx
[long_branch_regnum
];
2995 gcc_assert (current_function_has_lr_slot ());
2998 /* First emit the spill to the stack:
3001 write.l [1](sp),reg */
3006 rtx_insn
*delay
= NEXT_INSN (insn
);
3010 final_scan_insn (delay
, asm_out_file
, optimize
, 0, &seen
);
3011 PATTERN (delay
) = gen_blockage ();
3012 INSN_CODE (delay
) = -1;
3015 if (current_function_saves_fp ())
3016 output_asm_insn ("write.l 1(sp),%1", operands
);
3018 output_asm_insn ("write.l (sp),%1", operands
);
3021 /* Then emit the core sequence:
3027 We don't use r0 as the destination register of the branch because we
3028 want the Branch Pre-decode Logic of the GR6 to use the Address Load
3029 Array to predict the branch target. */
3030 output_asm_insn ("moviu %1,%%u %0", operands
);
3031 output_asm_insn ("movil %1,%%l %0", operands
);
3032 strcpy (str
, "bra ");
3034 strcat (str
, ",%1,%1");
3037 strcat (str
, "\t\t;long branch");
3038 output_asm_insn (str
, operands
);
3040 /* Finally emit the reload:
3042 read.l reg,[1](sp) */
3045 if (current_function_saves_fp ())
3046 output_asm_insn (" read.l %1,1(sp)", operands
);
3048 output_asm_insn (" read.l %1,(sp)", operands
);
3052 /* Or else, if the label is PC, then this is a return. */
3053 else if (label
== pc_rtx
)
3055 strcpy (str
, "bra ");
3057 strcat (str
, ",r21,r0%#\t\t;return");
3058 output_asm_insn (str
, operands
);
3061 /* Otherwise, this is a short branch. */
3064 strcpy (str
, "brr ");
3066 strcat (str
, ",%0%#");
3067 output_asm_insn (str
, operands
);
3073 /* Output an unconditional branch to LABEL. INSN is the instruction. */
3076 output_ubranch (rtx label
, rtx_insn
*insn
)
3078 return output_branch (label
, "tr", insn
);
3081 /* Output a conditional branch to LABEL. CODE is the comparison code.
3082 CC_MODE is the mode of the CC register. REVERSED is non-zero if we
3083 should reverse the sense of the comparison. INSN is the instruction. */
3086 output_cbranch (rtx label
, enum rtx_code code
, enum machine_mode cc_mode
,
3087 int reversed
, rtx_insn
*insn
)
3093 if (cc_mode
== CCFPmode
|| cc_mode
== CCFPEmode
)
3094 code
= reverse_condition_maybe_unordered (code
);
3096 code
= reverse_condition (code
);
3102 if (cc_mode
== CCCmode
)
3109 if (cc_mode
== CCCmode
)
3116 if (cc_mode
== CCNZmode
)
3127 if (cc_mode
== CCFPmode
|| cc_mode
== CCFPEmode
)
3134 if (cc_mode
== CCFPmode
|| cc_mode
== CCFPEmode
)
3135 cond
= "cs"; /* or "ns" */
3136 else if (cc_mode
== CCNZmode
)
3167 cond
= "cc"; /* or "nc" */
3182 /* These 2 comparison codes are not supported. */
3189 return output_branch (label
, cond
, insn
);
3192 /* Implement TARGET_PRINT_OPERAND_PUNCT_VALID_P. */
3195 visium_print_operand_punct_valid_p (unsigned char code
)
3200 /* Implement TARGET_PRINT_OPERAND. Output to stdio stream FILE the assembler
3201 syntax for an instruction operand OP subject to the modifier LETTER. */
3204 visium_print_operand (FILE *file
, rtx op
, int letter
)
3209 /* Output an insn in a delay slot. */
3211 visium_indent_opcode
= 1;
3213 fputs ("\n\t nop", file
);
3217 /* Print LS 8 bits of operand. */
3218 fprintf (file
, HOST_WIDE_INT_PRINT_UNSIGNED
, UINTVAL (op
) & 0xff);
3222 /* Print LS 16 bits of operand. */
3223 fprintf (file
, HOST_WIDE_INT_PRINT_UNSIGNED
, UINTVAL (op
) & 0xffff);
3227 /* Print MS 16 bits of operand. */
3229 HOST_WIDE_INT_PRINT_UNSIGNED
, (UINTVAL (op
) >> 16) & 0xffff);
3233 /* It's either a register or zero. */
3234 if (GET_CODE (op
) == REG
)
3235 fputs (reg_names
[REGNO (op
)], file
);
3237 fputs (reg_names
[0], file
);
3241 /* It's either a FP register or zero. */
3242 if (GET_CODE (op
) == REG
)
3243 fputs (reg_names
[REGNO (op
)], file
);
3245 fputs (reg_names
[FP_FIRST_REGNUM
], file
);
3249 switch (GET_CODE (op
))
3253 fputs (reg_names
[REGNO (op
) + 1], file
);
3255 fputs (reg_names
[REGNO (op
)], file
);
3261 output_addr_const (file
, op
);
3265 visium_print_operand_address (file
, GET_MODE (op
), XEXP (op
, 0));
3269 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (op
));
3273 asm_fprintf (file
, "%LL%d", CODE_LABEL_NUMBER (op
));
3277 visium_print_operand (file
, XEXP (op
, 1), letter
);
3281 fatal_insn ("illegal operand ", op
);
3285 /* Implement TARGET_PRINT_OPERAND_ADDRESS. Output to stdio stream FILE the
3286 assembler syntax for an instruction operand that is a memory reference
3287 whose address is ADDR. */
3290 visium_print_operand_address (FILE *file
, enum machine_mode mode
, rtx addr
)
3292 switch (GET_CODE (addr
))
3296 fprintf (file
, "(%s)", reg_names
[true_regnum (addr
)]);
3301 rtx x
= XEXP (addr
, 0), y
= XEXP (addr
, 1);
3303 switch (GET_CODE (x
))
3307 if (CONST_INT_P (y
))
3309 unsigned int regno
= true_regnum (x
);
3310 HOST_WIDE_INT val
= INTVAL (y
);
3328 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
"(%s)", val
,
3332 fatal_insn ("illegal operand address (1)", addr
);
3336 if (CONSTANT_P (x
) && CONSTANT_P (y
))
3337 output_addr_const (file
, addr
);
3339 fatal_insn ("illegal operand address (2)", addr
);
3349 output_addr_const (file
, addr
);
3353 if (NOTE_KIND (addr
) != NOTE_INSN_DELETED_LABEL
)
3354 fatal_insn ("illegal operand address (3)", addr
);
3358 asm_fprintf (file
, "%LL%d", CODE_LABEL_NUMBER (addr
));
3362 fatal_insn ("illegal operand address (4)", addr
);
3367 /* The Visium stack frames look like:
3369 Before call After call
3370 +-----------------------+ +-----------------------+
3372 high | previous | | previous |
3373 mem | frame | | frame |
3375 +-----------------------+ +-----------------------+
3377 | arguments on stack | | arguments on stack |
3379 SP+0->+-----------------------+ +-----------------------+
3380 | reg parm save area, |
3381 | only created for |
3382 | variable argument |
3384 +-----------------------+
3386 | register save area |
3388 +-----------------------+
3392 FP+8->+-----------------------+
3394 FP+4->+-----------------------+
3396 FP+0->+-----------------------+
3398 | alloca allocations |
3400 +-----------------------+
3402 low | arguments on stack |
3404 SP+0->+-----------------------+
3407 1) The "reg parm save area" does not exist for non variable argument fns.
3408 2) The FP register is not saved if `frame_pointer_needed' is zero and it
3409 is not altered in the current function.
3410 3) The return address is not saved if there is no frame pointer and the
3411 current function is leaf.
3412 4) If the return address is not saved and the static chain register is
3413 live in the function, we allocate the return address slot to be able
3414 to spill the register for a long branch. */
3416 /* Define the register classes for local purposes. */
3417 enum reg_type
{ general
, mdb
, mdc
, floating
, last_type
};
3419 #define GET_REG_TYPE(regno) \
3420 (GP_REGISTER_P (regno) ? general : \
3421 (regno) == MDB_REGNUM ? mdb : \
3422 (regno) == MDC_REGNUM ? mdc : \
3425 /* First regno of each register type. */
3426 const int first_regno
[last_type
] = {0, MDB_REGNUM
, MDC_REGNUM
, FP_FIRST_REGNUM
};
3428 /* Size in bytes of each register type. */
3429 const int reg_type_size
[last_type
] = {4, 8, 4, 4};
3431 /* Structure to be filled in by visium_compute_frame_size. */
3432 struct visium_frame_info
3434 unsigned int save_area_size
; /* # bytes in the reg parm save area. */
3435 unsigned int reg_size1
; /* # bytes to store first block of regs. */
3436 unsigned int reg_size2
; /* # bytes to store second block of regs. */
3437 unsigned int max_reg1
; /* max. regno in first block */
3438 unsigned int var_size
; /* # bytes that variables take up. */
3439 unsigned int save_fp
; /* Nonzero if fp must be saved. */
3440 unsigned int save_lr
; /* Nonzero if lr must be saved. */
3441 unsigned int lr_slot
; /* Nonzero if the lr slot is needed. */
3442 unsigned int combine
; /* Nonzero if we can combine the allocation of
3443 variables and regs. */
3444 unsigned int interrupt
; /* Nonzero if the function is an interrupt
3446 unsigned int mask
[last_type
]; /* Masks of saved regs: gp, mdb, mdc, fp */
3449 /* Current frame information calculated by visium_compute_frame_size. */
3450 static struct visium_frame_info current_frame_info
;
3452 /* Accessor for current_frame_info.save_fp. */
3455 current_function_saves_fp (void)
3457 return current_frame_info
.save_fp
!= 0;
3460 /* Accessor for current_frame_info.save_lr. */
3463 current_function_saves_lr (void)
3465 return current_frame_info
.save_lr
!= 0;
3468 /* Accessor for current_frame_info.lr_slot. */
3471 current_function_has_lr_slot (void)
3473 return current_frame_info
.lr_slot
!= 0;
3476 /* Return non-zero if register REGNO needs to be saved in the frame. */
3479 visium_save_reg_p (int interrupt
, int regno
)
3483 case HARD_FRAME_POINTER_REGNUM
:
3484 /* This register is call-saved but handled specially. */
3488 /* This register is fixed but can be modified. */
3493 /* These registers are fixed and hold the interrupt context. */
3494 return (interrupt
!= 0);
3497 /* The other fixed registers are either immutable or special. */
3498 if (fixed_regs
[regno
])
3507 if (df_regs_ever_live_p (regno
))
3510 else if (call_used_regs
[regno
])
3513 /* To save mdb requires two temporary registers. To save mdc or
3514 any of the floating registers requires one temporary
3515 register. If this is an interrupt routine, the temporary
3516 registers need to be saved as well. These temporary registers
3517 are call used, so we only need deal with the case of leaf
3519 if (regno
== PROLOGUE_TMP_REGNUM
)
3521 if (df_regs_ever_live_p (MDB_REGNUM
)
3522 || df_regs_ever_live_p (MDC_REGNUM
))
3525 for (int i
= FP_FIRST_REGNUM
; i
<= FP_LAST_REGNUM
; i
++)
3526 if (df_regs_ever_live_p (i
))
3530 else if (regno
== PROLOGUE_TMP_REGNUM
+ 1)
3532 if (df_regs_ever_live_p (MDB_REGNUM
))
3537 return df_regs_ever_live_p (regno
) && !call_used_regs
[regno
];
3540 /* Compute the frame size required by the function. This function is called
3541 during the reload pass and also by visium_expand_prologue. */
3544 visium_compute_frame_size (int size
)
3546 const int save_area_size
= visium_reg_parm_save_area_size
;
3547 const int var_size
= VISIUM_STACK_ALIGN (size
);
3549 = frame_pointer_needed
|| df_regs_ever_live_p (HARD_FRAME_POINTER_REGNUM
);
3550 const int save_lr
= frame_pointer_needed
|| !crtl
->is_leaf
;
3551 const int lr_slot
= !save_lr
&& df_regs_ever_live_p (long_branch_regnum
);
3552 const int local_frame_offset
3553 = (save_fp
+ save_lr
+ lr_slot
) * UNITS_PER_WORD
;
3554 const int interrupt
= visium_interrupt_function_p ();
3555 unsigned int mask
[last_type
];
3564 memset (mask
, 0, last_type
* sizeof (unsigned int));
3566 /* The registers may need stacking in 2 blocks since only 32 32-bit words
3567 can be indexed from a given base address. */
3568 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
3570 if (visium_save_reg_p (interrupt
, regno
))
3572 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3573 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3574 int nbytes
= reg_type_size
[reg_type
];
3576 if (reg_size1
+ nbytes
> 32 * UNITS_PER_WORD
)
3579 reg_size1
+= nbytes
;
3581 mask
[reg_type
] |= mask_bit
;
3585 for (regno
= max_reg1
+ 1; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
3587 if (visium_save_reg_p (interrupt
, regno
))
3589 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3590 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3591 int nbytes
= reg_type_size
[reg_type
];
3593 reg_size2
+= nbytes
;
3594 mask
[reg_type
] |= mask_bit
;
3598 reg_size
= reg_size2
? reg_size2
: reg_size1
;
3599 combine
= (local_frame_offset
+ var_size
+ reg_size
) <= 32 * UNITS_PER_WORD
;
3601 = local_frame_offset
+ var_size
+ reg_size2
+ reg_size1
+ save_area_size
;
3603 current_frame_info
.save_area_size
= save_area_size
;
3604 current_frame_info
.reg_size1
= reg_size1
;
3605 current_frame_info
.max_reg1
= max_reg1
;
3606 current_frame_info
.reg_size2
= reg_size2
;
3607 current_frame_info
.var_size
= var_size
;
3608 current_frame_info
.save_fp
= save_fp
;
3609 current_frame_info
.save_lr
= save_lr
;
3610 current_frame_info
.lr_slot
= lr_slot
;
3611 current_frame_info
.combine
= combine
;
3612 current_frame_info
.interrupt
= interrupt
;
3614 memcpy (current_frame_info
.mask
, mask
, last_type
* sizeof (unsigned int));
3619 /* Helper function for INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET). Define
3620 the offset between two registers, one to be eliminated, and the other its
3621 replacement, at the start of a routine. */
3624 visium_initial_elimination_offset (int from
, int to ATTRIBUTE_UNUSED
)
3626 const int save_fp
= current_frame_info
.save_fp
;
3627 const int save_lr
= current_frame_info
.save_lr
;
3628 const int lr_slot
= current_frame_info
.lr_slot
;
3631 if (from
== FRAME_POINTER_REGNUM
)
3632 offset
= (save_fp
+ save_lr
+ lr_slot
) * UNITS_PER_WORD
;
3633 else if (from
== ARG_POINTER_REGNUM
)
3634 offset
= visium_compute_frame_size (get_frame_size ());
3641 /* For an interrupt handler, we may be saving call-clobbered registers.
3642 Say the epilogue uses these in addition to the link register. */
3645 visium_epilogue_uses (int regno
)
3647 if (regno
== LINK_REGNUM
)
3650 if (reload_completed
)
3652 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3653 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3655 return (current_frame_info
.mask
[reg_type
] & mask_bit
) != 0;
3661 /* Wrapper around emit_insn that sets RTX_FRAME_RELATED_P on the insn. */
3664 emit_frame_insn (rtx x
)
3667 RTX_FRAME_RELATED_P (x
) = 1;
3671 /* Allocate ALLOC bytes on the stack and save the registers LOW_REGNO to
3672 HIGH_REGNO at OFFSET from the stack pointer. */
3675 visium_save_regs (int alloc
, int offset
, int low_regno
, int high_regno
)
3677 /* If this is an interrupt handler function, then mark the register
3678 stores as volatile. This will prevent the instruction scheduler
3679 from scrambling the order of register saves. */
3680 const int volatile_p
= current_frame_info
.interrupt
;
3683 /* Allocate the stack space. */
3684 emit_frame_insn (gen_addsi3_flags (stack_pointer_rtx
, stack_pointer_rtx
,
3687 for (regno
= low_regno
; regno
<= high_regno
; regno
++)
3689 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3690 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3693 if (current_frame_info
.mask
[reg_type
] & mask_bit
)
3695 offset
-= reg_type_size
[reg_type
];
3701 = gen_frame_mem (SImode
,
3702 plus_constant (Pmode
,
3703 stack_pointer_rtx
, offset
));
3704 MEM_VOLATILE_P (mem
) = volatile_p
;
3705 emit_frame_insn (gen_movsi (mem
, gen_rtx_REG (SImode
, regno
)));
3711 rtx tmp
= gen_rtx_REG (DImode
, PROLOGUE_TMP_REGNUM
);
3713 = gen_frame_mem (DImode
,
3714 plus_constant (Pmode
,
3715 stack_pointer_rtx
, offset
));
3716 rtx reg
= gen_rtx_REG (DImode
, regno
);
3717 MEM_VOLATILE_P (mem
) = volatile_p
;
3718 emit_insn (gen_movdi (tmp
, reg
));
3719 /* Do not generate CFI if in interrupt handler. */
3721 emit_insn (gen_movdi (mem
, tmp
));
3724 insn
= emit_frame_insn (gen_movdi (mem
, tmp
));
3725 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3726 gen_rtx_SET (mem
, reg
));
3733 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
);
3735 = gen_frame_mem (SImode
,
3736 plus_constant (Pmode
,
3737 stack_pointer_rtx
, offset
));
3738 rtx reg
= gen_rtx_REG (SImode
, regno
);
3739 MEM_VOLATILE_P (mem
) = volatile_p
;
3740 emit_insn (gen_movsi (tmp
, reg
));
3741 insn
= emit_frame_insn (gen_movsi (mem
, tmp
));
3742 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3743 gen_rtx_SET (mem
, reg
));
3749 rtx tmp
= gen_rtx_REG (SFmode
, PROLOGUE_TMP_REGNUM
);
3751 = gen_frame_mem (SFmode
,
3752 plus_constant (Pmode
,
3753 stack_pointer_rtx
, offset
));
3754 rtx reg
= gen_rtx_REG (SFmode
, regno
);
3755 MEM_VOLATILE_P (mem
) = volatile_p
;
3756 emit_insn (gen_movsf (tmp
, reg
));
3757 insn
= emit_frame_insn (gen_movsf (mem
, tmp
));
3758 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3759 gen_rtx_SET (mem
, reg
));
3770 /* This function generates the code for function entry. */
3773 visium_expand_prologue (void)
3775 const int frame_size
= visium_compute_frame_size (get_frame_size ());
3776 const int save_area_size
= current_frame_info
.save_area_size
;
3777 const int reg_size1
= current_frame_info
.reg_size1
;
3778 const int max_reg1
= current_frame_info
.max_reg1
;
3779 const int reg_size2
= current_frame_info
.reg_size2
;
3780 const int var_size
= current_frame_info
.var_size
;
3781 const int save_fp
= current_frame_info
.save_fp
;
3782 const int save_lr
= current_frame_info
.save_lr
;
3783 const int lr_slot
= current_frame_info
.lr_slot
;
3784 const int local_frame_offset
3785 = (save_fp
+ save_lr
+ lr_slot
) * UNITS_PER_WORD
;
3786 const int combine
= current_frame_info
.combine
;
3791 /* Save the frame size for future references. */
3792 visium_frame_size
= frame_size
;
3794 if (flag_stack_usage_info
)
3795 current_function_static_stack_size
= frame_size
;
3797 /* If the registers have to be stacked in 2 blocks, stack the first one. */
3800 visium_save_regs (reg_size1
+ save_area_size
, reg_size1
, 0, max_reg1
);
3801 reg_size
= reg_size2
;
3802 first_reg
= max_reg1
+ 1;
3803 fsize
= local_frame_offset
+ var_size
+ reg_size2
;
3807 reg_size
= reg_size1
;
3809 fsize
= local_frame_offset
+ var_size
+ reg_size1
+ save_area_size
;
3812 /* If we can't combine register stacking with variable allocation, partially
3813 allocate and stack the (remaining) registers now. */
3814 if (reg_size
&& !combine
)
3815 visium_save_regs (fsize
- local_frame_offset
- var_size
, reg_size
,
3816 first_reg
, FIRST_PSEUDO_REGISTER
- 1);
3818 /* If we can combine register stacking with variable allocation, fully
3819 allocate and stack the (remaining) registers now. */
3820 if (reg_size
&& combine
)
3821 visium_save_regs (fsize
, local_frame_offset
+ var_size
+ reg_size
,
3822 first_reg
, FIRST_PSEUDO_REGISTER
- 1);
3824 /* Otherwise space may still need to be allocated for the variables. */
3827 const int alloc_size
= reg_size
? local_frame_offset
+ var_size
: fsize
;
3829 if (alloc_size
> 65535)
3831 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
), insn
;
3832 emit_insn (gen_movsi (tmp
, GEN_INT (alloc_size
)));
3833 insn
= emit_frame_insn (gen_subsi3_flags (stack_pointer_rtx
,
3836 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3837 gen_rtx_SET (stack_pointer_rtx
,
3838 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
3839 GEN_INT (-alloc_size
))));
3842 emit_frame_insn (gen_addsi3_flags (stack_pointer_rtx
,
3844 GEN_INT (-alloc_size
)));
3848 emit_frame_insn (gen_movsi (gen_frame_mem (SImode
, stack_pointer_rtx
),
3849 hard_frame_pointer_rtx
));
3851 if (frame_pointer_needed
)
3852 emit_frame_insn (gen_stack_save ());
3858 /* Normally the frame pointer and link register get saved via
3863 Indexing off sp rather than fp to store the link register
3864 avoids presenting the instruction scheduler with an initial
3865 pipeline hazard. If however the frame is needed for eg.
3866 __builtin_return_address which needs to retrieve the saved
3867 value of the link register from the stack at fp + 4 then
3868 indexing from sp can confuse the dataflow, causing the link
3869 register to be retrieved before it has been saved. */
3870 if (cfun
->machine
->frame_needed
)
3871 base_rtx
= hard_frame_pointer_rtx
;
3873 base_rtx
= stack_pointer_rtx
;
3875 mem
= gen_frame_mem (SImode
,
3876 plus_constant (Pmode
,
3877 base_rtx
, save_fp
* UNITS_PER_WORD
));
3878 emit_frame_insn (gen_movsi (mem
, gen_rtx_REG (SImode
, LINK_REGNUM
)));
3882 static GTY(()) rtx cfa_restores
;
3884 /* Queue a REG_CFA_RESTORE note until next stack manipulation insn. */
3887 visium_add_cfa_restore_note (rtx reg
)
3889 cfa_restores
= alloc_reg_note (REG_CFA_RESTORE
, reg
, cfa_restores
);
3892 /* Add queued REG_CFA_RESTORE notes to INSN, if any. */
3895 visium_add_queued_cfa_restore_notes (rtx insn
)
3900 for (last
= cfa_restores
; XEXP (last
, 1); last
= XEXP (last
, 1))
3902 XEXP (last
, 1) = REG_NOTES (insn
);
3903 REG_NOTES (insn
) = cfa_restores
;
3904 cfa_restores
= NULL_RTX
;
3907 /* Restore the registers LOW_REGNO to HIGH_REGNO from the save area at OFFSET
3908 from the stack pointer and pop DEALLOC bytes off the stack. */
3911 visium_restore_regs (int dealloc
, int offset
, int high_regno
, int low_regno
)
3913 /* If this is an interrupt handler function, then mark the register
3914 restores as volatile. This will prevent the instruction scheduler
3915 from scrambling the order of register restores. */
3916 const int volatile_p
= current_frame_info
.interrupt
;
3917 int r30_offset
= -1;
3920 for (regno
= high_regno
; regno
>= low_regno
; --regno
)
3922 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3923 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3925 if (current_frame_info
.mask
[reg_type
] & mask_bit
)
3930 /* Postpone restoring the interrupted context registers
3931 until last, since they need to be preceded by a dsi. */
3934 else if (regno
== 30)
3935 r30_offset
= offset
;
3939 = gen_frame_mem (SImode
,
3940 plus_constant (Pmode
,
3943 rtx reg
= gen_rtx_REG (SImode
, regno
);
3944 MEM_VOLATILE_P (mem
) = volatile_p
;
3945 emit_insn (gen_movsi (reg
, mem
));
3946 visium_add_cfa_restore_note (reg
);
3952 rtx tmp
= gen_rtx_REG (DImode
, PROLOGUE_TMP_REGNUM
);
3954 = gen_frame_mem (DImode
,
3955 plus_constant (Pmode
,
3956 stack_pointer_rtx
, offset
));
3957 rtx reg
= gen_rtx_REG (DImode
, regno
);
3958 MEM_VOLATILE_P (mem
) = volatile_p
;
3959 emit_insn (gen_movdi (tmp
, mem
));
3960 emit_insn (gen_movdi (reg
, tmp
));
3961 /* Do not generate CFI if in interrupt handler. */
3963 visium_add_cfa_restore_note (reg
);
3969 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
);
3971 = gen_frame_mem (SImode
,
3972 plus_constant (Pmode
,
3973 stack_pointer_rtx
, offset
));
3974 rtx reg
= gen_rtx_REG (SImode
, regno
);
3975 MEM_VOLATILE_P (mem
) = volatile_p
;
3976 emit_insn (gen_movsi (tmp
, mem
));
3977 emit_insn (gen_movsi (reg
, tmp
));
3978 visium_add_cfa_restore_note (reg
);
3984 rtx tmp
= gen_rtx_REG (SFmode
, PROLOGUE_TMP_REGNUM
);
3986 = gen_frame_mem (SFmode
,
3987 plus_constant (Pmode
,
3988 stack_pointer_rtx
, offset
));
3989 rtx reg
= gen_rtx_REG (SFmode
, regno
);
3990 MEM_VOLATILE_P (mem
) = volatile_p
;
3991 emit_insn (gen_movsf (tmp
, mem
));
3992 emit_insn (gen_movsf (reg
, tmp
));
3993 visium_add_cfa_restore_note (reg
);
4001 offset
+= reg_type_size
[reg_type
];
4005 /* If the interrupted context needs to be restored, precede the
4006 restores of r29 and r30 by a dsi. */
4007 if (r30_offset
>= 0)
4009 emit_insn (gen_dsi ());
4010 emit_move_insn (gen_rtx_REG (SImode
, 30),
4011 gen_frame_mem (SImode
,
4012 plus_constant (Pmode
,
4015 emit_move_insn (gen_rtx_REG (SImode
, 29),
4016 gen_frame_mem (SImode
,
4017 plus_constant (Pmode
,
4022 /* Deallocate the stack space. */
4023 rtx insn
= emit_frame_insn (gen_stack_pop (GEN_INT (dealloc
)));
4024 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
4025 gen_rtx_SET (stack_pointer_rtx
,
4026 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
4027 GEN_INT (dealloc
))));
4028 visium_add_queued_cfa_restore_notes (insn
);
4031 /* This function generates the code for function exit. */
4034 visium_expand_epilogue (void)
4036 const int save_area_size
= current_frame_info
.save_area_size
;
4037 const int reg_size1
= current_frame_info
.reg_size1
;
4038 const int max_reg1
= current_frame_info
.max_reg1
;
4039 const int reg_size2
= current_frame_info
.reg_size2
;
4040 const int var_size
= current_frame_info
.var_size
;
4041 const int restore_fp
= current_frame_info
.save_fp
;
4042 const int restore_lr
= current_frame_info
.save_lr
;
4043 const int lr_slot
= current_frame_info
.lr_slot
;
4044 const int local_frame_offset
4045 = (restore_fp
+ restore_lr
+ lr_slot
) * UNITS_PER_WORD
;
4046 const int combine
= current_frame_info
.combine
;
4051 /* Do not bother restoring the stack pointer if it hasn't been changed in
4052 the function since it was saved _after_ the allocation of the frame. */
4053 if (!crtl
->sp_is_unchanging
)
4054 emit_insn (gen_stack_restore ());
4056 /* Restore the frame pointer if necessary. The usual code would be:
4061 but for the MCM this constitutes a stall/hazard so it is changed to:
4066 if the stack pointer has actually been restored. */
4071 if (TARGET_MCM
&& !crtl
->sp_is_unchanging
)
4072 src
= gen_frame_mem (SImode
, hard_frame_pointer_rtx
);
4074 src
= gen_frame_mem (SImode
, stack_pointer_rtx
);
4076 rtx insn
= emit_frame_insn (gen_movsi (hard_frame_pointer_rtx
, src
));
4077 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
4078 gen_rtx_SET (stack_pointer_rtx
,
4079 hard_frame_pointer_rtx
));
4080 visium_add_cfa_restore_note (hard_frame_pointer_rtx
);
4083 /* Restore the link register if necessary. */
4086 rtx mem
= gen_frame_mem (SImode
,
4087 plus_constant (Pmode
,
4089 restore_fp
* UNITS_PER_WORD
));
4090 rtx reg
= gen_rtx_REG (SImode
, LINK_REGNUM
);
4091 emit_insn (gen_movsi (reg
, mem
));
4092 visium_add_cfa_restore_note (reg
);
4095 /* If we have two blocks of registers, deal with the second one first. */
4098 reg_size
= reg_size2
;
4099 last_reg
= max_reg1
+ 1;
4100 fsize
= local_frame_offset
+ var_size
+ reg_size2
;
4104 reg_size
= reg_size1
;
4106 fsize
= local_frame_offset
+ var_size
+ reg_size1
+ save_area_size
;
4109 /* If the variable allocation could be combined with register stacking,
4110 restore the (remaining) registers and fully deallocate now. */
4111 if (reg_size
&& combine
)
4112 visium_restore_regs (fsize
, local_frame_offset
+ var_size
,
4113 FIRST_PSEUDO_REGISTER
- 1, last_reg
);
4115 /* Otherwise deallocate the variables first. */
4118 const int pop_size
= reg_size
? local_frame_offset
+ var_size
: fsize
;
4121 if (pop_size
> 65535)
4123 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
);
4124 emit_move_insn (tmp
, GEN_INT (pop_size
));
4125 insn
= emit_frame_insn (gen_stack_pop (tmp
));
4128 insn
= emit_frame_insn (gen_stack_pop (GEN_INT (pop_size
)));
4129 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
4130 gen_rtx_SET (stack_pointer_rtx
,
4131 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
4132 GEN_INT (pop_size
))));
4133 visium_add_queued_cfa_restore_notes (insn
);
4136 /* If the variable allocation couldn't be combined with register stacking,
4137 restore the (remaining) registers now and partially deallocate. */
4138 if (reg_size
&& !combine
)
4139 visium_restore_regs (fsize
- local_frame_offset
- var_size
, 0,
4140 FIRST_PSEUDO_REGISTER
- 1, last_reg
);
4142 /* If the first block of registers has yet to be restored, do it now. */
4144 visium_restore_regs (reg_size1
+ save_area_size
, 0, max_reg1
, 0);
4146 /* If this is an exception return, make the necessary stack adjustment. */
4147 if (crtl
->calls_eh_return
)
4148 emit_insn (gen_stack_pop (EH_RETURN_STACKADJ_RTX
));
4151 /* Return true if it is appropriate to emit `return' instructions in the
4152 body of a function. */
4155 visium_can_use_return_insn_p (void)
4157 return reload_completed
4158 && visium_frame_size
== 0
4159 && !visium_interrupt_function_p ();
4162 /* Return the register class required for an intermediate register used to
4163 copy a register of RCLASS from/to X. If no such intermediate register is
4164 required, return NO_REGS. If more than one such intermediate register is
4165 required, describe the one that is closest in the copy chain to the reload
4169 visium_secondary_reload (bool in_p ATTRIBUTE_UNUSED
, rtx x
,
4171 enum machine_mode mode ATTRIBUTE_UNUSED
,
4172 secondary_reload_info
*sri ATTRIBUTE_UNUSED
)
4174 int regno
= true_regnum (x
);
4176 /* For MDB, MDC and FP_REGS, a general register is needed for a move to
4178 if (regno
== -1 && (rclass
== MDB
|| rclass
== MDC
|| rclass
== FP_REGS
))
4179 return GENERAL_REGS
;
4181 /* Moves between MDB, MDC and FP_REGS also require a general register. */
4182 else if (((regno
== R_MDB
|| regno
== R_MDC
) && rclass
== FP_REGS
)
4183 || (FP_REGISTER_P (regno
) && (rclass
== MDB
|| rclass
== MDC
)))
4184 return GENERAL_REGS
;
4186 /* Finally an (unlikely ?) move between MDB and MDC needs a general reg. */
4187 else if ((regno
== R_MDB
&& rclass
== MDC
)
4188 || (rclass
== MDB
&& regno
== R_MDC
))
4189 return GENERAL_REGS
;
4194 /* Return true if pseudos that have been assigned to registers of RCLASS
4195 would likely be spilled because registers of RCLASS are needed for
4199 visium_class_likely_spilled_p (reg_class_t rclass ATTRIBUTE_UNUSED
)
4201 /* Return false for classes R1, R2 and R3, which are intended to be used
4202 only in the source code in conjunction with block move instructions. */
4206 /* Return the register number if OP is a REG or a SUBREG of a REG, and
4207 INVALID_REGNUM in all the other cases. */
4210 reg_or_subreg_regno (rtx op
)
4214 if (GET_CODE (op
) == REG
)
4216 else if (GET_CODE (op
) == SUBREG
&& GET_CODE (SUBREG_REG (op
)) == REG
)
4218 if (REGNO (SUBREG_REG (op
)) < FIRST_PSEUDO_REGISTER
)
4219 regno
= subreg_regno (op
);
4221 regno
= REGNO (SUBREG_REG (op
));
4224 regno
= INVALID_REGNUM
;
4229 #include "gt-visium.h"