1 /* Output routines for Visium.
2 Copyright (C) 2002-2017 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"
39 #include "diagnostic-core.h"
42 #include "fold-const.h"
43 #include "stor-layout.h"
47 #include "insn-attr.h"
51 #include "langhooks.h"
53 #include "tm-constrs.h"
55 #include "tree-pass.h"
59 /* This file should be included last. */
60 #include "target-def.h"
62 /* Enumeration of indexes into machine_libfunc_table. */
63 enum machine_libfunc_index
73 MLTI_set_trampoline_parity
,
78 struct GTY(()) machine_libfuncs
83 /* The table of Visium-specific libfuncs. */
84 static GTY(()) struct machine_libfuncs visium_libfuncs
;
86 #define vlt visium_libfuncs.table
88 /* Accessor macros for visium_libfuncs. */
89 #define long_int_memcpy_libfunc (vlt[MLTI_long_int_memcpy])
90 #define wrd_memcpy_libfunc (vlt[MLTI_wrd_memcpy])
91 #define byt_memcpy_libfunc (vlt[MLTI_byt_memcpy])
92 #define long_int_memset_libfunc (vlt[MLTI_long_int_memset])
93 #define wrd_memset_libfunc (vlt[MLTI_wrd_memset])
94 #define byt_memset_libfunc (vlt[MLTI_byt_memset])
95 #define set_trampoline_parity_libfunc (vlt[MLTI_set_trampoline_parity])
97 /* Machine specific function data. */
98 struct GTY (()) machine_function
100 /* Size of the frame of the function. */
103 /* Size of the reg parm save area, non-zero only for functions with variable
104 argument list. We cannot use the crtl->args.pretend_args_size machinery
105 for this purpose because this size is added to virtual_incoming_args_rtx
106 to give the location of the first parameter passed by the caller on the
107 stack and virtual_incoming_args_rtx is also the location of the first
108 parameter on the stack. So crtl->args.pretend_args_size can be non-zero
109 only if the first non-register named parameter is not passed entirely on
110 the stack and this runs afoul of the need to have a reg parm save area
111 even with a variable argument list starting on the stack because of the
112 separate handling of general and floating-point registers. */
113 int reg_parm_save_area_size
;
115 /* True if we have created an rtx which relies on the frame pointer. */
118 /* True if we have exposed the flags register. From this moment on, we
119 cannot generate simple operations for integer registers. We could
120 use reload_completed for this purpose, but this would cripple the
121 postreload CSE and GCSE passes which run before postreload split. */
125 #define visium_frame_size cfun->machine->frame_size
126 #define visium_reg_parm_save_area_size cfun->machine->reg_parm_save_area_size
127 #define visium_frame_needed cfun->machine->frame_needed
128 #define visium_flags_exposed cfun->machine->flags_exposed
130 /* 1 if the next opcode is to be specially indented. */
131 int visium_indent_opcode
= 0;
133 /* Register number used for long branches when LR isn't available. It
134 must be a call-used register since it isn't saved on function entry.
135 We do not care whether the branch is predicted or not on the GR6,
136 given how unlikely it is to have a long branch in a leaf function. */
137 static unsigned int long_branch_regnum
= 31;
139 static tree
visium_handle_interrupt_attr (tree
*, tree
, tree
, int, bool *);
140 static inline bool current_function_saves_fp (void);
141 static inline bool current_function_saves_lr (void);
142 static inline bool current_function_has_lr_slot (void);
144 /* Supported attributes:
145 interrupt -- specifies this function is an interrupt handler. */
146 static const struct attribute_spec visium_attribute_table
[] =
148 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
149 affects_type_identity } */
150 {"interrupt", 0, 0, true, false, false, visium_handle_interrupt_attr
, false},
151 {NULL
, 0, 0, false, false, false, NULL
, false}
154 static struct machine_function
*visium_init_machine_status (void);
156 /* Target hooks and TARGET_INITIALIZER */
158 static bool visium_pass_by_reference (cumulative_args_t
, machine_mode
,
161 static rtx
visium_function_arg (cumulative_args_t
, machine_mode
,
164 static void visium_function_arg_advance (cumulative_args_t
, machine_mode
,
167 static bool visium_return_in_memory (const_tree
, const_tree fntype
);
169 static rtx
visium_function_value (const_tree
, const_tree fn_decl_or_type
,
172 static rtx
visium_libcall_value (machine_mode
, const_rtx
);
174 static void visium_setup_incoming_varargs (cumulative_args_t
,
178 static void visium_va_start (tree valist
, rtx nextarg
);
180 static tree
visium_gimplify_va_arg (tree
, tree
, gimple_seq
*, gimple_seq
*);
182 static bool visium_function_ok_for_sibcall (tree
, tree
);
184 static bool visium_frame_pointer_required (void);
186 static tree
visium_build_builtin_va_list (void);
188 static rtx_insn
*visium_md_asm_adjust (vec
<rtx
> &, vec
<rtx
> &,
190 vec
<rtx
> &, HARD_REG_SET
&);
192 static bool visium_legitimate_constant_p (machine_mode
, rtx
);
194 static bool visium_legitimate_address_p (machine_mode
, rtx
, bool);
196 static bool visium_print_operand_punct_valid_p (unsigned char);
197 static void visium_print_operand (FILE *, rtx
, int);
198 static void visium_print_operand_address (FILE *, machine_mode
, rtx
);
200 static void visium_conditional_register_usage (void);
202 static rtx
visium_legitimize_address (rtx
, rtx
, machine_mode
);
204 static reg_class_t
visium_secondary_reload (bool, rtx
, reg_class_t
,
206 secondary_reload_info
*);
208 static bool visium_class_likely_spilled_p (reg_class_t
);
210 static void visium_trampoline_init (rtx
, tree
, rtx
);
212 static int visium_issue_rate (void);
214 static int visium_adjust_priority (rtx_insn
*, int);
216 static int visium_adjust_cost (rtx_insn
*, int, rtx_insn
*, int, unsigned int);
218 static int visium_register_move_cost (machine_mode
, reg_class_t
,
221 static int visium_memory_move_cost (machine_mode
, reg_class_t
, bool);
223 static bool visium_rtx_costs (rtx
, machine_mode
, int, int, int *, bool);
225 static void visium_option_override (void);
227 static void visium_init_libfuncs (void);
229 static unsigned int visium_reorg (void);
231 static unsigned int visium_hard_regno_nregs (unsigned int, machine_mode
);
233 static bool visium_hard_regno_mode_ok (unsigned int, machine_mode
);
235 static bool visium_modes_tieable_p (machine_mode
, machine_mode
);
237 static bool visium_can_change_mode_class (machine_mode
, machine_mode
,
240 static HOST_WIDE_INT
visium_constant_alignment (const_tree
, HOST_WIDE_INT
);
242 /* Setup the global target hooks structure. */
244 #undef TARGET_MAX_ANCHOR_OFFSET
245 #define TARGET_MAX_ANCHOR_OFFSET 31
247 #undef TARGET_PASS_BY_REFERENCE
248 #define TARGET_PASS_BY_REFERENCE visium_pass_by_reference
250 #undef TARGET_FUNCTION_ARG
251 #define TARGET_FUNCTION_ARG visium_function_arg
253 #undef TARGET_FUNCTION_ARG_ADVANCE
254 #define TARGET_FUNCTION_ARG_ADVANCE visium_function_arg_advance
256 #undef TARGET_RETURN_IN_MEMORY
257 #define TARGET_RETURN_IN_MEMORY visium_return_in_memory
259 #undef TARGET_FUNCTION_VALUE
260 #define TARGET_FUNCTION_VALUE visium_function_value
262 #undef TARGET_LIBCALL_VALUE
263 #define TARGET_LIBCALL_VALUE visium_libcall_value
265 #undef TARGET_SETUP_INCOMING_VARARGS
266 #define TARGET_SETUP_INCOMING_VARARGS visium_setup_incoming_varargs
268 #undef TARGET_EXPAND_BUILTIN_VA_START
269 #define TARGET_EXPAND_BUILTIN_VA_START visium_va_start
271 #undef TARGET_BUILD_BUILTIN_VA_LIST
272 #define TARGET_BUILD_BUILTIN_VA_LIST visium_build_builtin_va_list
274 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
275 #define TARGET_GIMPLIFY_VA_ARG_EXPR visium_gimplify_va_arg
277 #undef TARGET_LEGITIMATE_CONSTANT_P
278 #define TARGET_LEGITIMATE_CONSTANT_P visium_legitimate_constant_p
281 #define TARGET_LRA_P hook_bool_void_false
283 #undef TARGET_LEGITIMATE_ADDRESS_P
284 #define TARGET_LEGITIMATE_ADDRESS_P visium_legitimate_address_p
286 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
287 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P visium_print_operand_punct_valid_p
288 #undef TARGET_PRINT_OPERAND
289 #define TARGET_PRINT_OPERAND visium_print_operand
290 #undef TARGET_PRINT_OPERAND_ADDRESS
291 #define TARGET_PRINT_OPERAND_ADDRESS visium_print_operand_address
293 #undef TARGET_ATTRIBUTE_TABLE
294 #define TARGET_ATTRIBUTE_TABLE visium_attribute_table
296 #undef TARGET_ADDRESS_COST
297 #define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
299 #undef TARGET_STRICT_ARGUMENT_NAMING
300 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
302 #undef TARGET_SCHED_ISSUE_RATE
303 #define TARGET_SCHED_ISSUE_RATE visium_issue_rate
305 #undef TARGET_SCHED_ADJUST_PRIORITY
306 #define TARGET_SCHED_ADJUST_PRIORITY visium_adjust_priority
308 #undef TARGET_SCHED_ADJUST_COST
309 #define TARGET_SCHED_ADJUST_COST visium_adjust_cost
311 #undef TARGET_MEMORY_MOVE_COST
312 #define TARGET_MEMORY_MOVE_COST visium_memory_move_cost
314 #undef TARGET_REGISTER_MOVE_COST
315 #define TARGET_REGISTER_MOVE_COST visium_register_move_cost
317 #undef TARGET_RTX_COSTS
318 #define TARGET_RTX_COSTS visium_rtx_costs
320 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
321 #define TARGET_FUNCTION_OK_FOR_SIBCALL visium_function_ok_for_sibcall
323 #undef TARGET_FRAME_POINTER_REQUIRED
324 #define TARGET_FRAME_POINTER_REQUIRED visium_frame_pointer_required
326 #undef TARGET_SECONDARY_RELOAD
327 #define TARGET_SECONDARY_RELOAD visium_secondary_reload
329 #undef TARGET_CLASS_LIKELY_SPILLED_P
330 #define TARGET_CLASS_LIKELY_SPILLED_P visium_class_likely_spilled_p
332 #undef TARGET_LEGITIMIZE_ADDRESS
333 #define TARGET_LEGITIMIZE_ADDRESS visium_legitimize_address
335 #undef TARGET_OPTION_OVERRIDE
336 #define TARGET_OPTION_OVERRIDE visium_option_override
338 #undef TARGET_INIT_LIBFUNCS
339 #define TARGET_INIT_LIBFUNCS visium_init_libfuncs
341 #undef TARGET_CONDITIONAL_REGISTER_USAGE
342 #define TARGET_CONDITIONAL_REGISTER_USAGE visium_conditional_register_usage
344 #undef TARGET_TRAMPOLINE_INIT
345 #define TARGET_TRAMPOLINE_INIT visium_trampoline_init
347 #undef TARGET_MD_ASM_ADJUST
348 #define TARGET_MD_ASM_ADJUST visium_md_asm_adjust
350 #undef TARGET_FLAGS_REGNUM
351 #define TARGET_FLAGS_REGNUM FLAGS_REGNUM
353 #undef TARGET_HARD_REGNO_NREGS
354 #define TARGET_HARD_REGNO_NREGS visium_hard_regno_nregs
356 #undef TARGET_HARD_REGNO_MODE_OK
357 #define TARGET_HARD_REGNO_MODE_OK visium_hard_regno_mode_ok
359 #undef TARGET_MODES_TIEABLE_P
360 #define TARGET_MODES_TIEABLE_P visium_modes_tieable_p
362 #undef TARGET_CAN_CHANGE_MODE_CLASS
363 #define TARGET_CAN_CHANGE_MODE_CLASS visium_can_change_mode_class
365 #undef TARGET_CONSTANT_ALIGNMENT
366 #define TARGET_CONSTANT_ALIGNMENT visium_constant_alignment
368 struct gcc_target targetm
= TARGET_INITIALIZER
;
372 const pass_data pass_data_visium_reorg
=
376 OPTGROUP_NONE
, /* optinfo_flags */
377 TV_MACH_DEP
, /* tv_id */
378 0, /* properties_required */
379 0, /* properties_provided */
380 0, /* properties_destroyed */
381 0, /* todo_flags_start */
382 0, /* todo_flags_finish */
385 class pass_visium_reorg
: public rtl_opt_pass
388 pass_visium_reorg(gcc::context
*ctxt
)
389 : rtl_opt_pass(pass_data_visium_reorg
, ctxt
)
392 /* opt_pass methods: */
393 virtual unsigned int execute (function
*)
395 return visium_reorg ();
398 }; // class pass_work_around_errata
403 make_pass_visium_reorg (gcc::context
*ctxt
)
405 return new pass_visium_reorg (ctxt
);
408 /* Options override for Visium. */
411 visium_option_override (void)
414 warning (OPT_fpic
, "-fpic is not supported");
416 warning (OPT_fPIC
, "-fPIC is not supported");
418 /* MCM is the default in the GR5/GR6 era. */
419 target_flags
|= MASK_MCM
;
421 /* FPU is the default with MCM, but don't override an explicit option. */
422 if ((target_flags_explicit
& MASK_FPU
) == 0)
423 target_flags
|= MASK_FPU
;
425 /* The supervisor mode is the default. */
426 if ((target_flags_explicit
& MASK_SV_MODE
) == 0)
427 target_flags
|= MASK_SV_MODE
;
429 /* The GR6 has the Block Move Instructions and an IEEE-compliant FPU. */
430 if (visium_cpu_and_features
== PROCESSOR_GR6
)
432 target_flags
|= MASK_BMI
;
433 if (target_flags
& MASK_FPU
)
434 target_flags
|= MASK_FPU_IEEE
;
437 /* Set -mtune from -mcpu if not specified. */
438 if (!global_options_set
.x_visium_cpu
)
439 visium_cpu
= visium_cpu_and_features
;
441 /* Align functions on 256-byte (32-quadword) for GR5 and 64-byte (8-quadword)
442 boundaries for GR6 so they start a new burst mode window. */
443 if (align_functions
== 0)
445 if (visium_cpu
== PROCESSOR_GR6
)
446 align_functions
= 64;
448 align_functions
= 256;
450 /* Allow the size of compilation units to double because of inlining.
451 In practice the global size of the object code is hardly affected
452 because the additional instructions will take up the padding. */
453 maybe_set_param_value (PARAM_INLINE_UNIT_GROWTH
, 100,
454 global_options
.x_param_values
,
455 global_options_set
.x_param_values
);
458 /* Likewise for loops. */
459 if (align_loops
== 0)
461 if (visium_cpu
== PROCESSOR_GR6
)
466 /* But not if they are too far away from a 256-byte boundary. */
467 align_loops_max_skip
= 31;
471 /* Align all jumps on quadword boundaries for the burst mode, and even
472 on 8-quadword boundaries for GR6 so they start a new window. */
473 if (align_jumps
== 0)
475 if (visium_cpu
== PROCESSOR_GR6
)
481 /* We register a machine-specific pass. This pass must be scheduled as
482 late as possible so that we have the (essentially) final form of the
483 insn stream to work on. Registering the pass must be done at start up.
484 It's convenient to do it here. */
485 opt_pass
*visium_reorg_pass
= make_pass_visium_reorg (g
);
486 struct register_pass_info insert_pass_visium_reorg
=
488 visium_reorg_pass
, /* pass */
489 "dbr", /* reference_pass_name */
490 1, /* ref_pass_instance_number */
491 PASS_POS_INSERT_AFTER
/* po_op */
493 register_pass (&insert_pass_visium_reorg
);
496 /* Register the Visium-specific libfuncs with the middle-end. */
499 visium_init_libfuncs (void)
502 long_int_memcpy_libfunc
= init_one_libfunc ("__long_int_memcpy");
503 wrd_memcpy_libfunc
= init_one_libfunc ("__wrd_memcpy");
504 byt_memcpy_libfunc
= init_one_libfunc ("__byt_memcpy");
506 long_int_memset_libfunc
= init_one_libfunc ("__long_int_memset");
507 wrd_memset_libfunc
= init_one_libfunc ("__wrd_memset");
508 byt_memset_libfunc
= init_one_libfunc ("__byt_memset");
510 set_trampoline_parity_libfunc
= init_one_libfunc ("__set_trampoline_parity");
513 /* Return the number of instructions that can issue on the same cycle. */
516 visium_issue_rate (void)
531 /* Return the adjusted PRIORITY of INSN. */
534 visium_adjust_priority (rtx_insn
*insn
, int priority
)
536 /* On the GR5, we slightly increase the priority of writes in order to avoid
537 scheduling a read on the next cycle. This is necessary in addition to the
538 associated insn reservation because there are no data dependencies.
539 We also slightly increase the priority of reads from ROM in order to group
540 them as much as possible. These reads are a bit problematic because they
541 conflict with the instruction fetches, i.e. the data and instruction buses
542 tread on each other's toes when they are executed. */
543 if (visium_cpu
== PROCESSOR_GR5
546 && recog_memoized (insn
) >= 0)
548 enum attr_type attr_type
= get_attr_type (insn
);
549 if (attr_type
== TYPE_REG_MEM
550 || (attr_type
== TYPE_MEM_REG
551 && MEM_READONLY_P (SET_SRC (PATTERN (insn
)))))
558 /* Adjust the cost of a scheduling dependency. Return the new cost of
559 a dependency LINK of INSN on DEP_INSN. COST is the current cost. */
562 visium_adjust_cost (rtx_insn
*insn
, int dep_type
, rtx_insn
*dep_insn
, int cost
,
565 enum attr_type attr_type
;
567 /* Don't adjust costs for true dependencies as they are described with
568 bypasses. But we make an exception for the first scheduling pass to
569 help the subsequent postreload compare elimination pass. */
570 if (dep_type
== REG_DEP_TRUE
)
572 if (!reload_completed
573 && recog_memoized (insn
) >= 0
574 && get_attr_type (insn
) == TYPE_CMP
)
576 rtx pat
= PATTERN (insn
);
577 gcc_assert (GET_CODE (pat
) == SET
);
578 rtx src
= SET_SRC (pat
);
580 /* Only the branches can be modified by the postreload compare
581 elimination pass, not the cstores because they accept only
582 unsigned comparison operators and they are eliminated if
583 one of the operands is zero. */
584 if (GET_CODE (src
) == IF_THEN_ELSE
585 && XEXP (XEXP (src
, 0), 1) == const0_rtx
586 && recog_memoized (dep_insn
) >= 0)
588 enum attr_type dep_attr_type
= get_attr_type (dep_insn
);
590 /* The logical instructions use CCmode and thus work with any
591 comparison operator, whereas the arithmetic instructions use
592 CCNZmode and thus work with only a small subset. */
593 if (dep_attr_type
== TYPE_LOGIC
594 || (dep_attr_type
== TYPE_ARITH
595 && visium_nz_comparison_operator (XEXP (src
, 0),
605 if (recog_memoized (insn
) < 0)
608 attr_type
= get_attr_type (insn
);
610 /* Anti dependency: DEP_INSN reads a register that INSN writes some
612 if (dep_type
== REG_DEP_ANTI
)
614 /* On the GR5, the latency of FP instructions needs to be taken into
615 account for every dependency involving a write. */
616 if (attr_type
== TYPE_REG_FP
&& visium_cpu
== PROCESSOR_GR5
)
619 rtx pat
= PATTERN (insn
);
620 rtx dep_pat
= PATTERN (dep_insn
);
622 if (GET_CODE (pat
) != SET
|| GET_CODE (dep_pat
) != SET
)
623 /* If this happens, we have to extend this to schedule
624 optimally. Return 0 for now. */
627 if (reg_mentioned_p (SET_DEST (pat
), SET_SRC (dep_pat
)))
629 if (recog_memoized (dep_insn
) < 0)
632 switch (get_attr_type (dep_insn
))
640 /* A fload can't be issued until a preceding arithmetic
641 operation has finished if the target of the fload is
642 any of the sources (or destination) of the arithmetic
643 operation. Note that the latency may be (much)
644 greater than this if the preceding instruction
645 concerned is in a queue. */
646 return insn_default_latency (dep_insn
);
654 /* On the GR6, we try to make sure that the link register is restored
655 sufficiently ahead of the return as to yield a correct prediction
656 from the branch predictor. By default there is no true dependency
657 but an anti dependency between them, so we simply reuse it. */
658 else if (attr_type
== TYPE_RET
&& visium_cpu
== PROCESSOR_GR6
)
660 rtx dep_pat
= PATTERN (dep_insn
);
661 if (GET_CODE (dep_pat
) == SET
662 && REG_P (SET_DEST (dep_pat
))
663 && REGNO (SET_DEST (dep_pat
)) == LINK_REGNUM
)
667 /* For other anti dependencies, the cost is 0. */
671 /* Output dependency: DEP_INSN writes a register that INSN writes some
673 else if (dep_type
== REG_DEP_OUTPUT
)
675 /* On the GR5, the latency of FP instructions needs to be taken into
676 account for every dependency involving a write. */
677 if (attr_type
== TYPE_REG_FP
&& visium_cpu
== PROCESSOR_GR5
)
680 rtx pat
= PATTERN (insn
);
681 rtx dep_pat
= PATTERN (dep_insn
);
683 if (GET_CODE (pat
) != SET
|| GET_CODE (dep_pat
) != SET
)
684 /* If this happens, we have to extend this to schedule
685 optimally. Return 0 for now. */
688 if (reg_mentioned_p (SET_DEST (pat
), SET_DEST (dep_pat
)))
690 if (recog_memoized (dep_insn
) < 0)
693 switch (get_attr_type (dep_insn
))
701 /* A fload can't be issued until a preceding arithmetic
702 operation has finished if the target of the fload is
703 the destination of the arithmetic operation. Note that
704 the latency may be (much) greater than this if the
705 preceding instruction concerned is in a queue. */
706 return insn_default_latency (dep_insn
);
714 /* For other output dependencies, the cost is 0. */
721 /* Handle an "interrupt_handler" attribute; arguments as in
722 struct attribute_spec.handler. */
725 visium_handle_interrupt_attr (tree
*node
, tree name
,
726 tree args ATTRIBUTE_UNUSED
,
727 int flags ATTRIBUTE_UNUSED
,
730 if (TREE_CODE (*node
) != FUNCTION_DECL
)
732 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
734 *no_add_attrs
= true;
736 else if (!TARGET_SV_MODE
)
738 error ("an interrupt handler cannot be compiled with -muser-mode");
739 *no_add_attrs
= true;
745 /* Return non-zero if the current function is an interrupt function. */
748 visium_interrupt_function_p (void)
751 lookup_attribute ("interrupt",
752 DECL_ATTRIBUTES (current_function_decl
)) != NULL_TREE
;
755 /* Conditionally modify the settings of the register file. */
758 visium_conditional_register_usage (void)
760 /* If the supervisor mode is disabled, mask some general registers. */
763 if (visium_cpu_and_features
== PROCESSOR_GR5
)
765 fixed_regs
[24] = call_used_regs
[24] = 1;
766 fixed_regs
[25] = call_used_regs
[25] = 1;
767 fixed_regs
[26] = call_used_regs
[26] = 1;
768 fixed_regs
[27] = call_used_regs
[27] = 1;
769 fixed_regs
[28] = call_used_regs
[28] = 1;
770 call_really_used_regs
[24] = 0;
771 call_really_used_regs
[25] = 0;
772 call_really_used_regs
[26] = 0;
773 call_really_used_regs
[27] = 0;
774 call_really_used_regs
[28] = 0;
777 fixed_regs
[31] = call_used_regs
[31] = 1;
778 call_really_used_regs
[31] = 0;
780 /* We also need to change the long-branch register. */
781 if (visium_cpu_and_features
== PROCESSOR_GR5
)
782 long_branch_regnum
= 20;
784 long_branch_regnum
= 28;
787 /* If the FPU is disabled, mask the FP registers. */
790 for (int i
= FP_FIRST_REGNUM
; i
<= FP_LAST_REGNUM
; i
++)
792 fixed_regs
[i
] = call_used_regs
[i
] = 1;
793 call_really_used_regs
[i
] = 0;
798 /* Prepend to CLOBBERS hard registers that are automatically clobbered for
799 an asm We do this for the FLAGS to maintain source compatibility with
800 the original cc0-based compiler. */
803 visium_md_asm_adjust (vec
<rtx
> &/*outputs*/, vec
<rtx
> &/*inputs*/,
804 vec
<const char *> &/*constraints*/,
805 vec
<rtx
> &clobbers
, HARD_REG_SET
&clobbered_regs
)
807 clobbers
.safe_push (gen_rtx_REG (CCmode
, FLAGS_REGNUM
));
808 SET_HARD_REG_BIT (clobbered_regs
, FLAGS_REGNUM
);
812 /* Return true if X is a legitimate constant for a MODE immediate operand.
813 X is guaranteed to satisfy the CONSTANT_P predicate. */
816 visium_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED
,
817 rtx x ATTRIBUTE_UNUSED
)
822 /* Compute the alignment for a variable. The alignment of an aggregate is
823 set to be at least that of a scalar less than or equal to it in size. */
826 visium_data_alignment (tree type
, unsigned int align
)
828 if (AGGREGATE_TYPE_P (type
)
830 && TREE_CODE (TYPE_SIZE (type
)) == INTEGER_CST
&& align
< 32)
832 if (TREE_INT_CST_LOW (TYPE_SIZE (type
)) >= 32)
835 if (TREE_INT_CST_LOW (TYPE_SIZE (type
)) >= 16 && align
< 16)
842 /* Implement TARGET_CONSTANT_ALIGNMENT. */
845 visium_constant_alignment (const_tree exp
, HOST_WIDE_INT align
)
847 return visium_data_alignment (TREE_TYPE (exp
), align
);
850 /* Helper function for HARD_REGNO_RENAME_OK (FROM, TO). Return non-zero if
851 it is OK to rename a hard register FROM to another hard register TO. */
854 visium_hard_regno_rename_ok (unsigned int from ATTRIBUTE_UNUSED
,
857 /* If the function doesn't save LR, then the long-branch register will be
858 used for long branches so we need to know whether it is live before the
859 frame layout is computed. */
860 if (!current_function_saves_lr () && to
== long_branch_regnum
)
863 /* Interrupt functions can only use registers that have already been
864 saved by the prologue, even if they would normally be call-clobbered. */
866 && !df_regs_ever_live_p (to
)
867 && visium_interrupt_function_p ())
873 /* Implement TARGET_HARD_REGNO_NREGS. */
876 visium_hard_regno_nregs (unsigned int regno
, machine_mode mode
)
878 if (regno
== MDB_REGNUM
)
879 return CEIL (GET_MODE_SIZE (mode
), 2 * UNITS_PER_WORD
);
880 return CEIL (GET_MODE_SIZE (mode
), UNITS_PER_WORD
);
883 /* Implement TARGET_HARD_REGNO_MODE_OK.
885 Modes with sizes which cross from the one register class to the
886 other cannot be allowed. Only single floats are allowed in the
887 floating point registers, and only fixed point values in the EAM
891 visium_hard_regno_mode_ok (unsigned int regno
, machine_mode mode
)
893 if (GP_REGISTER_P (regno
))
894 return GP_REGISTER_P (end_hard_regno (mode
, regno
) - 1);
896 if (FP_REGISTER_P (regno
))
897 return mode
== SFmode
|| (mode
== SImode
&& TARGET_FPU_IEEE
);
899 return (GET_MODE_CLASS (mode
) == MODE_INT
900 && visium_hard_regno_nregs (regno
, mode
) == 1);
903 /* Implement TARGET_MODES_TIEABLE_P. */
906 visium_modes_tieable_p (machine_mode mode1
, machine_mode mode2
)
908 return (GET_MODE_CLASS (mode1
) == MODE_INT
909 && GET_MODE_CLASS (mode2
) == MODE_INT
);
912 /* Return true if it is ok to do sibling call optimization for the specified
913 call expression EXP. DECL will be the called function, or NULL if this
914 is an indirect call. */
917 visium_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED
,
918 tree exp ATTRIBUTE_UNUSED
)
920 return !visium_interrupt_function_p ();
923 /* Prepare operands for a move define_expand in MODE. */
926 prepare_move_operands (rtx
*operands
, machine_mode mode
)
928 /* If the output is not a register, the input must be. */
929 if (GET_CODE (operands
[0]) == MEM
&& !reg_or_0_operand (operands
[1], mode
))
930 operands
[1] = force_reg (mode
, operands
[1]);
933 /* Return true if the operands are valid for a simple move insn. */
936 ok_for_simple_move_operands (rtx
*operands
, machine_mode mode
)
938 /* One of the operands must be a register. */
939 if (!register_operand (operands
[0], mode
)
940 && !reg_or_0_operand (operands
[1], mode
))
943 /* Once the flags are exposed, no simple moves between integer registers. */
944 if (visium_flags_exposed
945 && gpc_reg_operand (operands
[0], mode
)
946 && gpc_reg_operand (operands
[1], mode
))
952 /* Return true if the operands are valid for a simple move strict insn. */
955 ok_for_simple_move_strict_operands (rtx
*operands
, machine_mode mode
)
957 /* Once the flags are exposed, no simple moves between integer registers.
958 Note that, in QImode only, a zero source counts as an integer register
959 since it will be emitted as r0. */
960 if (visium_flags_exposed
961 && gpc_reg_operand (operands
[0], mode
)
962 && (gpc_reg_operand (operands
[1], mode
)
963 || (mode
== QImode
&& operands
[1] == const0_rtx
)))
969 /* Return true if the operands are valid for a simple arithmetic or logical
973 ok_for_simple_arith_logic_operands (rtx
*, machine_mode
)
975 /* Once the flags are exposed, no simple arithmetic or logical operations
976 between integer registers. */
977 return !visium_flags_exposed
;
980 /* Return non-zero if a branch or call instruction will be emitting a nop
981 into its delay slot. */
984 empty_delay_slot (rtx_insn
*insn
)
988 /* If no previous instruction (should not happen), return true. */
989 if (PREV_INSN (insn
) == NULL
)
992 seq
= NEXT_INSN (PREV_INSN (insn
));
993 if (GET_CODE (PATTERN (seq
)) == SEQUENCE
)
999 /* Wrapper around single_set which returns the second SET of a pair if the
1000 first SET is to the flags register. */
1003 single_set_and_flags (rtx_insn
*insn
)
1005 if (multiple_sets (insn
))
1007 rtx pat
= PATTERN (insn
);
1008 if (XVECLEN (pat
, 0) == 2
1009 && GET_CODE (XVECEXP (pat
, 0, 0)) == SET
1010 && REG_P (SET_DEST (XVECEXP (pat
, 0, 0)))
1011 && REGNO (SET_DEST (XVECEXP (pat
, 0, 0))) == FLAGS_REGNUM
)
1012 return XVECEXP (pat
, 0, 1);
1015 return single_set (insn
);
1018 /* This is called with OUT_INSN an instruction setting a (base) register
1019 and IN_INSN a read or a write. Return 1 if these instructions together
1020 constitute a pipeline hazard.
1022 On the original architecture, a pipeline data hazard occurs when the Dest
1023 of one instruction becomes the SrcA for an immediately following READ or
1024 WRITE instruction with a non-zero index (indexing occurs at the decode
1025 stage and so a NOP must be inserted in-between for this to work).
1032 On the MCM, the non-zero index condition is lifted but the hazard is
1033 patched up by the hardware through the injection of wait states:
1038 We nevertheless try to schedule instructions around this. */
1041 gr5_hazard_bypass_p (rtx_insn
*out_insn
, rtx_insn
*in_insn
)
1043 rtx out_set
, in_set
, dest
, memexpr
;
1044 unsigned int out_reg
, in_reg
;
1046 /* A CALL is storage register class, but the link register is of no
1048 if (GET_CODE (out_insn
) == CALL_INSN
)
1051 out_set
= single_set_and_flags (out_insn
);
1052 dest
= SET_DEST (out_set
);
1054 /* Should be no stall/hazard if OUT_INSN is MEM := ???. This only
1055 occurs prior to reload. */
1056 if (GET_CODE (dest
) == MEM
)
1059 if (GET_CODE (dest
) == STRICT_LOW_PART
)
1060 dest
= XEXP (dest
, 0);
1061 if (GET_CODE (dest
) == SUBREG
)
1062 dest
= SUBREG_REG (dest
);
1063 out_reg
= REGNO (dest
);
1065 in_set
= single_set_and_flags (in_insn
);
1067 /* If IN_INSN is MEM := MEM, it's the source that counts. */
1068 if (GET_CODE (SET_SRC (in_set
)) == MEM
)
1069 memexpr
= XEXP (SET_SRC (in_set
), 0);
1071 memexpr
= XEXP (SET_DEST (in_set
), 0);
1073 if (GET_CODE (memexpr
) == PLUS
)
1075 memexpr
= XEXP (memexpr
, 0);
1076 if (GET_CODE (memexpr
) == SUBREG
)
1077 in_reg
= REGNO (SUBREG_REG (memexpr
));
1079 in_reg
= REGNO (memexpr
);
1081 if (in_reg
== out_reg
)
1084 else if (TARGET_MCM
)
1086 if (GET_CODE (memexpr
) == STRICT_LOW_PART
)
1087 memexpr
= XEXP (memexpr
, 0);
1088 if (GET_CODE (memexpr
) == SUBREG
)
1089 memexpr
= SUBREG_REG (memexpr
);
1090 in_reg
= REGNO (memexpr
);
1092 if (in_reg
== out_reg
)
1099 /* Return true if INSN is an empty asm instruction. */
1102 empty_asm_p (rtx insn
)
1104 rtx body
= PATTERN (insn
);
1107 if (GET_CODE (body
) == ASM_INPUT
)
1108 templ
= XSTR (body
, 0);
1109 else if (asm_noperands (body
) >= 0)
1110 templ
= decode_asm_operands (body
, NULL
, NULL
, NULL
, NULL
, NULL
);
1114 return (templ
&& templ
[0] == '\0');
1117 /* Insert a NOP immediately before INSN wherever there is a pipeline hazard.
1118 LAST_REG records the register set in the last insn and LAST_INSN_CALL
1119 records whether the last insn was a call insn. */
1122 gr5_avoid_hazard (rtx_insn
*insn
, unsigned int *last_reg
, bool *last_insn_call
)
1124 unsigned int dest_reg
= 0;
1127 switch (GET_CODE (insn
))
1131 *last_insn_call
= true;
1135 /* If this is an empty asm, just skip it. */
1136 if (!empty_asm_p (insn
))
1139 *last_insn_call
= false;
1144 /* If this is an empty asm, just skip it. */
1145 if (empty_asm_p (insn
))
1153 set
= single_set_and_flags (insn
);
1154 if (set
!= NULL_RTX
)
1156 rtx dest
= SET_DEST (set
);
1157 const bool double_p
= GET_MODE_SIZE (GET_MODE (dest
)) > UNITS_PER_WORD
;
1160 if (GET_CODE (SET_SRC (set
)) == MEM
)
1162 memrtx
= XEXP (SET_SRC (set
), 0);
1163 if (GET_CODE (dest
) == STRICT_LOW_PART
)
1164 dest
= XEXP (dest
, 0);
1166 dest_reg
= REGNO (dest
);
1168 /* If this is a DI or DF mode memory to register
1169 copy, then if rd = rs we get
1174 otherwise the order is
1181 unsigned int base_reg
;
1183 if (GET_CODE (memrtx
) == PLUS
)
1184 base_reg
= REGNO (XEXP (memrtx
, 0));
1186 base_reg
= REGNO (memrtx
);
1188 if (dest_reg
!= base_reg
)
1193 else if (GET_CODE (dest
) == MEM
)
1194 memrtx
= XEXP (dest
, 0);
1196 else if (GET_MODE_CLASS (GET_MODE (dest
)) != MODE_CC
)
1198 if (GET_CODE (dest
) == STRICT_LOW_PART
1199 ||GET_CODE (dest
) == ZERO_EXTRACT
)
1200 dest
= XEXP (dest
, 0);
1201 dest_reg
= REGNO (dest
);
1203 if (GET_CODE (SET_SRC (set
)) == REG
)
1205 unsigned int srcreg
= REGNO (SET_SRC (set
));
1207 /* Check for rs := rs, which will be deleted. */
1208 if (srcreg
== dest_reg
)
1211 /* In the case of a DI or DF mode move from register to
1212 register there is overlap if rd = rs + 1 in which case
1213 the order of the copies is reversed :
1218 if (double_p
&& dest_reg
!= srcreg
+ 1)
1223 /* If this is the delay slot of a call insn, any register it sets
1225 if (*last_insn_call
)
1228 /* If the previous insn sets the value of a register, and this insn
1229 uses a base register, check for the pipeline hazard where it is
1230 the same register in each case. */
1231 if (*last_reg
!= 0 && memrtx
!= NULL_RTX
)
1233 unsigned int reg
= 0;
1235 /* Check for an index (original architecture). */
1236 if (GET_CODE (memrtx
) == PLUS
)
1237 reg
= REGNO (XEXP (memrtx
, 0));
1239 /* Check for an MCM target or rs := [rs], in DI or DF mode. */
1240 else if (TARGET_MCM
|| (double_p
&& REGNO (memrtx
) == dest_reg
))
1241 reg
= REGNO (memrtx
);
1243 /* Remove any pipeline hazard by inserting a NOP. */
1244 if (reg
== *last_reg
)
1248 "inserting nop before insn %d\n", INSN_UID (insn
));
1249 emit_insn_after (gen_hazard_nop (), prev_active_insn (insn
));
1250 emit_insn_after (gen_blockage (), insn
);
1254 *last_reg
= dest_reg
;
1257 *last_insn_call
= false;
1260 /* Go through the instruction stream and insert nops where necessary to avoid
1261 pipeline hazards. There are two cases:
1263 1. On the original architecture, it is invalid to set the value of a
1264 (base) register and then use it in an address with a non-zero index
1265 in the next instruction.
1267 2. On the MCM, setting the value of a (base) register and then using
1268 it in address (including with zero index) in the next instruction
1269 will result in a pipeline stall of 3 cycles. */
1272 gr5_hazard_avoidance (void)
1274 unsigned int last_reg
= 0;
1275 bool last_insn_call
= false;
1278 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
1281 rtx pat
= PATTERN (insn
);
1283 if (GET_CODE (pat
) == SEQUENCE
)
1285 for (int i
= 0; i
< XVECLEN (pat
, 0); i
++)
1286 gr5_avoid_hazard (as_a
<rtx_insn
*> (XVECEXP (pat
, 0, i
)),
1287 &last_reg
, &last_insn_call
);
1290 else if (GET_CODE (insn
) == CALL_INSN
)
1292 /* This call is going to get a nop in its delay slot. */
1294 last_insn_call
= false;
1298 gr5_avoid_hazard (insn
, &last_reg
, &last_insn_call
);
1301 else if (GET_CODE (insn
) == BARRIER
)
1305 /* Perform a target-specific pass over the instruction stream. The compiler
1306 will run it at all optimization levels, just after the point at which it
1307 normally does delayed-branch scheduling. */
1312 if (visium_cpu
== PROCESSOR_GR5
)
1313 gr5_hazard_avoidance ();
1317 /* Return true if an argument must be passed by indirect reference. */
1320 visium_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED
,
1321 machine_mode mode ATTRIBUTE_UNUSED
,
1323 bool named ATTRIBUTE_UNUSED
)
1325 return type
&& (AGGREGATE_TYPE_P (type
) || TREE_CODE (type
) == VECTOR_TYPE
);
1328 /* Define how arguments are passed.
1330 A range of general registers and floating registers is available
1331 for passing arguments. When the class of registers which an
1332 argument would normally use is exhausted, that argument, is passed
1333 in the overflow region of the stack. No argument is split between
1334 registers and stack.
1336 Arguments of type float or _Complex float go in FP registers if FP
1337 hardware is available. If there is no FP hardware, arguments of
1338 type float go in general registers. All other arguments are passed
1339 in general registers. */
1342 visium_function_arg (cumulative_args_t pcum_v
, machine_mode mode
,
1343 const_tree type ATTRIBUTE_UNUSED
,
1344 bool named ATTRIBUTE_UNUSED
)
1347 CUMULATIVE_ARGS
*ca
= get_cumulative_args (pcum_v
);
1349 size
= (GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
1350 if (mode
== VOIDmode
)
1353 /* Scalar or complex single precision floating point arguments are returned
1354 in floating registers. */
1356 && ((GET_MODE_CLASS (mode
) == MODE_FLOAT
1357 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
)
1358 || (GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
1359 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
* 2)))
1361 if (ca
->frcount
+ size
<= MAX_ARGS_IN_FP_REGISTERS
)
1362 return gen_rtx_REG (mode
, FP_ARG_FIRST
+ ca
->frcount
);
1367 if (ca
->grcount
+ size
<= MAX_ARGS_IN_GP_REGISTERS
)
1368 return gen_rtx_REG (mode
, ca
->grcount
+ GP_ARG_FIRST
);
1373 /* Update the summarizer variable pointed to by PCUM_V to advance past an
1374 argument in the argument list. The values MODE, TYPE and NAMED describe
1375 that argument. Once this is done, the variable CUM is suitable for
1376 analyzing the _following_ argument with visium_function_arg. */
1379 visium_function_arg_advance (cumulative_args_t pcum_v
,
1381 const_tree type ATTRIBUTE_UNUSED
,
1384 int size
= (GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
1386 CUMULATIVE_ARGS
*ca
= get_cumulative_args (pcum_v
);
1388 /* Scalar or complex single precision floating point arguments are returned
1389 in floating registers. */
1391 && ((GET_MODE_CLASS (mode
) == MODE_FLOAT
1392 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
)
1393 || (GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
1394 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
* 2)))
1396 if (ca
->frcount
+ size
<= MAX_ARGS_IN_FP_REGISTERS
)
1397 ca
->frcount
+= size
;
1401 ca
->frcount
= MAX_ARGS_IN_FP_REGISTERS
;
1406 /* Everything else goes in a general register, if enough are
1408 if (ca
->grcount
+ size
<= MAX_ARGS_IN_GP_REGISTERS
)
1409 ca
->grcount
+= size
;
1413 ca
->grcount
= MAX_ARGS_IN_GP_REGISTERS
;
1418 ca
->stack_words
+= stack_size
;
1421 /* Specify whether to return the return value in memory. */
1424 visium_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
1426 return (AGGREGATE_TYPE_P (type
) || TREE_CODE (type
) == VECTOR_TYPE
);
1429 /* Define how scalar values are returned. */
1432 visium_function_value_1 (machine_mode mode
)
1434 /* Scalar or complex single precision floating point values
1435 are returned in floating register f1. */
1437 && ((GET_MODE_CLASS (mode
) == MODE_FLOAT
1438 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
)
1439 || (GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
1440 && GET_MODE_SIZE (mode
) <= UNITS_PER_HWFPVALUE
* 2)))
1441 return gen_rtx_REG (mode
, FP_RETURN_REGNUM
);
1443 /* All others are returned in r1. */
1444 return gen_rtx_REG (mode
, RETURN_REGNUM
);
1447 /* Return an RTX representing the place where a function returns or receives
1448 a value of data type RET_TYPE. */
1451 visium_function_value (const_tree ret_type
,
1452 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1453 bool outgoing ATTRIBUTE_UNUSED
)
1455 return visium_function_value_1 (TYPE_MODE (ret_type
));
1458 /* Return an RTX representing the place where the library function result will
1462 visium_libcall_value (machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
1464 return visium_function_value_1 (mode
);
1467 /* Store the anonymous register arguments into the stack so that all the
1468 arguments appear to have been passed consecutively on the stack. */
1471 visium_setup_incoming_varargs (cumulative_args_t pcum_v
,
1474 int *pretend_size ATTRIBUTE_UNUSED
,
1477 cumulative_args_t local_args_so_far
;
1478 CUMULATIVE_ARGS local_copy
;
1479 CUMULATIVE_ARGS
*locargs
;
1480 int gp_saved
, fp_saved
, size
;
1482 /* Create an internal cumulative_args_t pointer to internally define
1483 storage to ensure calling TARGET_FUNCTION_ARG_ADVANCE does not
1484 make global changes. */
1485 local_args_so_far
.p
= &local_copy
;
1486 locargs
= get_cumulative_args (pcum_v
);
1489 local_args_so_far
.magic
= CUMULATIVE_ARGS_MAGIC
;
1492 local_copy
.grcount
= locargs
->grcount
;
1493 local_copy
.frcount
= locargs
->frcount
;
1494 local_copy
.stack_words
= locargs
->stack_words
;
1496 /* The caller has advanced ARGS_SO_FAR up to, but not beyond, the last named
1497 argument. Advance a local copy of ARGS_SO_FAR past the last "real" named
1498 argument, to find out how many registers are left over. */
1499 TARGET_FUNCTION_ARG_ADVANCE (local_args_so_far
, mode
, type
, 1);
1501 /* Find how many registers we need to save. */
1502 locargs
= get_cumulative_args (local_args_so_far
);
1503 gp_saved
= MAX_ARGS_IN_GP_REGISTERS
- locargs
->grcount
;
1504 fp_saved
= (TARGET_FPU
? MAX_ARGS_IN_FP_REGISTERS
- locargs
->frcount
: 0);
1505 size
= (gp_saved
* UNITS_PER_WORD
) + (fp_saved
* UNITS_PER_HWFPVALUE
);
1507 if (!no_rtl
&& size
> 0)
1509 /* To avoid negative offsets, which are not valid addressing modes on
1510 the Visium, we create a base register for the pretend args. */
1513 plus_constant (Pmode
, virtual_incoming_args_rtx
, -size
));
1518 = gen_rtx_MEM (BLKmode
,
1519 plus_constant (Pmode
,
1521 fp_saved
* UNITS_PER_HWFPVALUE
));
1522 MEM_NOTRAP_P (mem
) = 1;
1523 set_mem_alias_set (mem
, get_varargs_alias_set ());
1524 move_block_from_reg (locargs
->grcount
+ GP_ARG_FIRST
, mem
, gp_saved
);
1529 rtx mem
= gen_rtx_MEM (BLKmode
, ptr
);
1530 MEM_NOTRAP_P (mem
) = 1;
1531 set_mem_alias_set (mem
, get_varargs_alias_set ());
1532 gcc_assert (UNITS_PER_WORD
== UNITS_PER_HWFPVALUE
);
1533 move_block_from_reg (locargs
->frcount
+ FP_ARG_FIRST
, mem
, fp_saved
);
1537 visium_reg_parm_save_area_size
= size
;
1540 /* Define the `__builtin_va_list' type for the ABI. */
1543 visium_build_builtin_va_list (void)
1545 tree f_ovfl
, f_gbase
, f_fbase
, f_gbytes
, f_fbytes
, record
;
1547 record
= (*lang_hooks
.types
.make_type
) (RECORD_TYPE
);
1548 f_ovfl
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1549 get_identifier ("__overflow_argptr"), ptr_type_node
);
1550 f_gbase
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1551 get_identifier ("__gpr_base"), ptr_type_node
);
1552 f_fbase
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1553 get_identifier ("__fpr_base"), ptr_type_node
);
1554 f_gbytes
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1555 get_identifier ("__gpr_bytes"),
1556 short_unsigned_type_node
);
1557 f_fbytes
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
1558 get_identifier ("__fpr_bytes"),
1559 short_unsigned_type_node
);
1561 DECL_FIELD_CONTEXT (f_ovfl
) = record
;
1562 DECL_FIELD_CONTEXT (f_gbase
) = record
;
1563 DECL_FIELD_CONTEXT (f_fbase
) = record
;
1564 DECL_FIELD_CONTEXT (f_gbytes
) = record
;
1565 DECL_FIELD_CONTEXT (f_fbytes
) = record
;
1566 TYPE_FIELDS (record
) = f_ovfl
;
1567 TREE_CHAIN (f_ovfl
) = f_gbase
;
1568 TREE_CHAIN (f_gbase
) = f_fbase
;
1569 TREE_CHAIN (f_fbase
) = f_gbytes
;
1570 TREE_CHAIN (f_gbytes
) = f_fbytes
;
1571 layout_type (record
);
1576 /* Implement `va_start' for varargs and stdarg. */
1579 visium_va_start (tree valist
, rtx nextarg ATTRIBUTE_UNUSED
)
1581 const CUMULATIVE_ARGS
*ca
= &crtl
->args
.info
;
1582 int gp_saved
= MAX_ARGS_IN_GP_REGISTERS
- ca
->grcount
;
1583 int fp_saved
= (TARGET_FPU
? MAX_ARGS_IN_FP_REGISTERS
- ca
->frcount
: 0);
1584 int named_stack_size
= ca
->stack_words
* UNITS_PER_WORD
, offset
;
1585 tree f_ovfl
, f_gbase
, f_fbase
, f_gbytes
, f_fbytes
;
1586 tree ovfl
, gbase
, gbytes
, fbase
, fbytes
, t
;
1588 f_ovfl
= TYPE_FIELDS (va_list_type_node
);
1589 f_gbase
= TREE_CHAIN (f_ovfl
);
1590 f_fbase
= TREE_CHAIN (f_gbase
);
1591 f_gbytes
= TREE_CHAIN (f_fbase
);
1592 f_fbytes
= TREE_CHAIN (f_gbytes
);
1593 ovfl
= build3 (COMPONENT_REF
, TREE_TYPE (f_ovfl
), valist
, f_ovfl
, NULL_TREE
);
1594 gbase
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbase
), valist
, f_gbase
,
1596 fbase
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbase
), valist
, f_fbase
,
1598 gbytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbytes
), valist
, f_gbytes
,
1600 fbytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbytes
), valist
, f_fbytes
,
1603 /* Store the stacked vararg pointer in the OVFL member. */
1604 t
= make_tree (TREE_TYPE (ovfl
), virtual_incoming_args_rtx
);
1605 t
= fold_build_pointer_plus_hwi (t
, named_stack_size
);
1606 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ovfl
), ovfl
, t
);
1607 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1609 /* Store the base address of the GPR save area into GBASE. */
1610 t
= make_tree (TREE_TYPE (gbase
), virtual_incoming_args_rtx
);
1611 offset
= MAX_ARGS_IN_GP_REGISTERS
* UNITS_PER_WORD
;
1612 t
= fold_build_pointer_plus_hwi (t
, -offset
);
1613 t
= build2 (MODIFY_EXPR
, TREE_TYPE (gbase
), gbase
, t
);
1614 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1616 /* Store the base address of the FPR save area into FBASE. */
1619 t
= make_tree (TREE_TYPE (fbase
), virtual_incoming_args_rtx
);
1620 offset
= gp_saved
* UNITS_PER_WORD
1621 + MAX_ARGS_IN_FP_REGISTERS
* UNITS_PER_HWFPVALUE
;
1622 t
= fold_build_pointer_plus_hwi (t
, -offset
);
1623 t
= build2 (MODIFY_EXPR
, TREE_TYPE (fbase
), fbase
, t
);
1624 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1627 /* Fill in the GBYTES member. */
1628 t
= build2 (MODIFY_EXPR
, TREE_TYPE (gbytes
), gbytes
,
1629 size_int (gp_saved
* UNITS_PER_WORD
));
1630 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1632 /* Fill in the FBYTES member. */
1633 t
= build2 (MODIFY_EXPR
, TREE_TYPE (fbytes
),
1634 fbytes
, size_int (fp_saved
* UNITS_PER_HWFPVALUE
));
1635 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1638 /* Implement `va_arg'. */
1641 visium_gimplify_va_arg (tree valist
, tree type
, gimple_seq
*pre_p
,
1644 tree f_ovfl
, f_gbase
, f_fbase
, f_gbytes
, f_fbytes
;
1645 tree ovfl
, base
, bytes
;
1646 HOST_WIDE_INT size
, rsize
;
1647 const bool by_reference_p
1648 = pass_by_reference (NULL
, TYPE_MODE (type
), type
, false);
1649 const bool float_reg_arg_p
1650 = (TARGET_FPU
&& !by_reference_p
1651 && ((GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
1652 && GET_MODE_SIZE (TYPE_MODE (type
)) <= UNITS_PER_HWFPVALUE
)
1653 || (GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_COMPLEX_FLOAT
1654 && (GET_MODE_SIZE (TYPE_MODE (type
))
1655 <= UNITS_PER_HWFPVALUE
* 2))));
1656 const int max_save_area_size
1657 = (float_reg_arg_p
? MAX_ARGS_IN_FP_REGISTERS
* UNITS_PER_HWFPVALUE
1658 : MAX_ARGS_IN_GP_REGISTERS
* UNITS_PER_WORD
);
1660 tree lab_false
, lab_over
, addr
;
1661 tree ptrtype
= build_pointer_type (type
);
1665 t
= visium_gimplify_va_arg (valist
, ptrtype
, pre_p
, post_p
);
1666 return build_va_arg_indirect_ref (t
);
1669 size
= int_size_in_bytes (type
);
1670 rsize
= (size
+ UNITS_PER_WORD
- 1) & -UNITS_PER_WORD
;
1671 f_ovfl
= TYPE_FIELDS (va_list_type_node
);
1672 f_gbase
= TREE_CHAIN (f_ovfl
);
1673 f_fbase
= TREE_CHAIN (f_gbase
);
1674 f_gbytes
= TREE_CHAIN (f_fbase
);
1675 f_fbytes
= TREE_CHAIN (f_gbytes
);
1677 /* We maintain separate pointers and offsets for floating-point and
1678 general registers, but we need similar code in both cases.
1682 BYTES be the number of unused bytes in the register save area.
1683 BASE be the base address of the register save area.
1684 OFFS be the current offset into the register save area. Either
1685 MAX_ARGS_IN_GP_REGISTERS * UNITS_PER_WORD - bytes or
1686 MAX_ARGS_IN_FP_REGISTERS * UNITS_PER_HWFPVALUE - bytes
1687 depending upon whether the argument is in general or floating
1689 ADDR_RTX be the address of the argument.
1690 RSIZE be the size in bytes of the argument.
1691 OVFL be the pointer to the stack overflow area.
1693 The code we want is:
1695 1: if (bytes >= rsize)
1697 3: addr_rtx = base + offs;
1709 addr
= create_tmp_var (ptr_type_node
, "addr");
1710 lab_false
= create_artificial_label (UNKNOWN_LOCATION
);
1711 lab_over
= create_artificial_label (UNKNOWN_LOCATION
);
1712 if (float_reg_arg_p
)
1713 bytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbytes
), unshare_expr (valist
),
1714 f_fbytes
, NULL_TREE
);
1716 bytes
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbytes
), unshare_expr (valist
),
1717 f_gbytes
, NULL_TREE
);
1719 /* [1] Emit code to branch if bytes < rsize. */
1720 t
= fold_convert (TREE_TYPE (bytes
), size_int (rsize
));
1721 t
= build2 (LT_EXPR
, boolean_type_node
, bytes
, t
);
1722 u
= build1 (GOTO_EXPR
, void_type_node
, lab_false
);
1723 t
= build3 (COND_EXPR
, void_type_node
, t
, u
, NULL_TREE
);
1724 gimplify_and_add (t
, pre_p
);
1726 /* [3] Emit code for: addr_rtx = base + offs, where
1727 offs = max_save_area_size - bytes. */
1728 t
= fold_convert (sizetype
, bytes
);
1729 offs
= build2 (MINUS_EXPR
, sizetype
, size_int (max_save_area_size
), t
);
1730 if (float_reg_arg_p
)
1731 base
= build3 (COMPONENT_REF
, TREE_TYPE (f_fbase
), valist
, f_fbase
,
1734 base
= build3 (COMPONENT_REF
, TREE_TYPE (f_gbase
), valist
, f_gbase
,
1737 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (base
), base
, offs
);
1738 t
= build2 (MODIFY_EXPR
, void_type_node
, addr
, t
);
1739 gimplify_and_add (t
, pre_p
);
1741 /* [4] Emit code for: bytes -= rsize. */
1742 t
= fold_convert (TREE_TYPE (bytes
), size_int (rsize
));
1743 t
= build2 (MINUS_EXPR
, TREE_TYPE (bytes
), bytes
, t
);
1744 t
= build2 (MODIFY_EXPR
, TREE_TYPE (bytes
), bytes
, t
);
1745 gimplify_and_add (t
, pre_p
);
1747 /* [6] Emit code to branch over the else clause, then the label. */
1748 t
= build1 (GOTO_EXPR
, void_type_node
, lab_over
);
1749 gimplify_and_add (t
, pre_p
);
1750 t
= build1 (LABEL_EXPR
, void_type_node
, lab_false
);
1751 gimplify_and_add (t
, pre_p
);
1753 /* [8] Emit code for: bytes = 0. */
1754 t
= fold_convert (TREE_TYPE (bytes
), size_int (0));
1755 t
= build2 (MODIFY_EXPR
, TREE_TYPE (bytes
), unshare_expr (bytes
), t
);
1756 gimplify_and_add (t
, pre_p
);
1758 /* [9] Emit code for: addr_rtx = ovfl. */
1759 ovfl
= build3 (COMPONENT_REF
, TREE_TYPE (f_ovfl
), valist
, f_ovfl
, NULL_TREE
);
1760 t
= build2 (MODIFY_EXPR
, void_type_node
, addr
, ovfl
);
1761 gimplify_and_add (t
, pre_p
);
1763 /* [10] Emit code for: ovfl += rsize. */
1764 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (ovfl
), ovfl
, size_int (rsize
));
1765 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ovfl
), unshare_expr (ovfl
), t
);
1766 gimplify_and_add (t
, pre_p
);
1767 t
= build1 (LABEL_EXPR
, void_type_node
, lab_over
);
1768 gimplify_and_add (t
, pre_p
);
1770 /* Emit a big-endian correction if size < UNITS_PER_WORD. */
1771 if (size
< UNITS_PER_WORD
)
1773 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (addr
), addr
,
1774 size_int (UNITS_PER_WORD
- size
));
1775 t
= build2 (MODIFY_EXPR
, void_type_node
, addr
, t
);
1776 gimplify_and_add (t
, pre_p
);
1779 addr
= fold_convert (ptrtype
, addr
);
1781 return build_va_arg_indirect_ref (addr
);
1784 /* Return true if OP is an offset suitable for use as a displacement in the
1785 address of a memory access in mode MODE. */
1788 rtx_ok_for_offset_p (machine_mode mode
, rtx op
)
1790 if (!CONST_INT_P (op
) || INTVAL (op
) < 0)
1796 return INTVAL (op
) <= 31;
1799 return (INTVAL (op
) % 2) == 0 && INTVAL (op
) < 63;
1803 return (INTVAL (op
) % 4) == 0 && INTVAL (op
) < 127;
1807 return (INTVAL (op
) % 4) == 0 && INTVAL (op
) < 123;
1814 /* Return whether X is a legitimate memory address for a memory operand
1817 Legitimate addresses are defined in two variants: a strict variant
1818 and a non-strict one. The STRICT parameter chooses which variant
1819 is desired by the caller.
1821 The strict variant is used in the reload pass. It must be defined
1822 so that any pseudo-register that has not been allocated a hard
1823 register is considered a memory reference. This is because in
1824 contexts where some kind of register is required, a
1825 pseudo-register with no hard register must be rejected. For
1826 non-hard registers, the strict variant should look up the
1827 `reg_renumber' array; it should then proceed using the hard
1828 register number in the array, or treat the pseudo as a memory
1829 reference if the array holds `-1'.
1831 The non-strict variant is used in other passes. It must be
1832 defined to accept all pseudo-registers in every context where some
1833 kind of register is required. */
1836 visium_legitimate_address_p (machine_mode mode
, rtx x
, bool strict
)
1841 /* If X is base+disp, check that we have an appropriate offset. */
1842 if (GET_CODE (x
) == PLUS
)
1844 if (!rtx_ok_for_offset_p (mode
, XEXP (x
, 1)))
1851 /* Now check the base: it must be either a register or a subreg thereof. */
1852 if (GET_CODE (base
) == SUBREG
)
1853 base
= SUBREG_REG (base
);
1857 regno
= REGNO (base
);
1859 /* For the strict variant, the register must be REGNO_OK_FOR_BASE_P. */
1861 return REGNO_OK_FOR_BASE_P (regno
);
1863 /* For the non-strict variant, the register may also be a pseudo. */
1864 return BASE_REGISTER_P (regno
) || regno
>= FIRST_PSEUDO_REGISTER
;
1867 /* Try machine-dependent ways of modifying an illegitimate address
1868 to be legitimate. If we find one, return the new, valid address.
1869 This macro is used in only one place: `memory_address' in explow.c.
1871 OLDX is the address as it was before break_out_memory_refs was called.
1872 In some cases it is useful to look at this to decide what needs to be done.
1874 MODE and WIN are passed so that this macro can use
1875 GO_IF_LEGITIMATE_ADDRESS.
1877 It is always safe for this macro to do nothing. It exists to recognize
1878 opportunities to optimize the output.
1882 memory (reg + <out of range int>)
1886 base_int = <out of range int> & ~mask
1887 ptr_reg = reg + base_int
1888 memory (ptr_reg + <out of range int> - base_int)
1890 Thus ptr_reg is a base register for a range of addresses,
1891 which should help CSE.
1893 For a 1 byte reference mask is 0x1f
1894 for a 2 byte reference mask is 0x3f
1895 For a 4 byte reference mask is 0x7f
1897 This reflects the indexing range of the processor.
1899 For a > 4 byte reference the mask is 0x7f provided all of the words
1900 can be accessed with the base address obtained. Otherwise a mask
1903 On rare occasions an unaligned base register value with an
1904 unaligned offset is generated. Unaligned offsets are left alone for
1908 visium_legitimize_address (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
1911 if (GET_CODE (x
) == PLUS
1912 && GET_CODE (XEXP (x
, 1)) == CONST_INT
1913 && GET_CODE (XEXP (x
, 0)) == REG
&& mode
!= BLKmode
)
1915 int offset
= INTVAL (XEXP (x
, 1));
1916 int size
= GET_MODE_SIZE (mode
);
1917 int mask
= (size
== 1 ? 0x1f : (size
== 2 ? 0x3f : 0x7f));
1918 int mask1
= (size
== 1 ? 0 : (size
== 2 ? 1 : 3));
1919 int offset_base
= offset
& ~mask
;
1921 /* Check that all of the words can be accessed. */
1922 if (4 < size
&& 0x80 < size
+ offset
- offset_base
)
1923 offset_base
= offset
& ~0x3f;
1924 if (offset_base
!= 0 && offset_base
!= offset
&& (offset
& mask1
) == 0)
1926 rtx ptr_reg
= force_reg (Pmode
,
1927 gen_rtx_PLUS (Pmode
,
1929 GEN_INT (offset_base
)));
1931 return plus_constant (Pmode
, ptr_reg
, offset
- offset_base
);
1938 /* Perform a similar function to visium_legitimize_address, but this time
1939 for reload. Generating new registers is not an option here. Parts
1940 that need reloading are indicated by calling push_reload. */
1943 visium_legitimize_reload_address (rtx x
, machine_mode mode
, int opnum
,
1944 int type
, int ind ATTRIBUTE_UNUSED
)
1946 rtx newrtx
, tem
= NULL_RTX
;
1948 if (mode
== BLKmode
)
1951 if (optimize
&& GET_CODE (x
) == PLUS
)
1952 tem
= simplify_binary_operation (PLUS
, GET_MODE (x
), XEXP (x
, 0),
1955 newrtx
= tem
? tem
: x
;
1956 if (GET_CODE (newrtx
) == PLUS
1957 && GET_CODE (XEXP (newrtx
, 1)) == CONST_INT
1958 && GET_CODE (XEXP (newrtx
, 0)) == REG
1959 && BASE_REGISTER_P (REGNO (XEXP (newrtx
, 0))))
1961 int offset
= INTVAL (XEXP (newrtx
, 1));
1962 int size
= GET_MODE_SIZE (mode
);
1963 int mask
= (size
== 1 ? 0x1f : (size
== 2 ? 0x3f : 0x7f));
1964 int mask1
= (size
== 1 ? 0 : (size
== 2 ? 1 : 3));
1965 int offset_base
= offset
& ~mask
;
1967 /* Check that all of the words can be accessed. */
1968 if (4 < size
&& 0x80 < size
+ offset
- offset_base
)
1969 offset_base
= offset
& ~0x3f;
1971 if (offset_base
&& (offset
& mask1
) == 0)
1973 rtx temp
= gen_rtx_PLUS (Pmode
,
1974 XEXP (newrtx
, 0), GEN_INT (offset_base
));
1976 x
= gen_rtx_PLUS (Pmode
, temp
, GEN_INT (offset
- offset_base
));
1977 push_reload (XEXP (x
, 0), 0, &XEXP (x
, 0), 0,
1978 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
,
1979 (enum reload_type
) type
);
1987 /* Return the cost of moving data of mode MODE from a register in class FROM to
1988 one in class TO. A value of 2 is the default; other values are interpreted
1989 relative to that. */
1992 visium_register_move_cost (machine_mode mode
, reg_class_t from
,
1995 const int numwords
= (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
) ? 1 : 2;
1997 if (from
== MDB
|| to
== MDB
)
1999 else if (from
== MDC
|| to
== MDC
|| (from
== FP_REGS
) != (to
== FP_REGS
))
2000 return 4 * numwords
;
2002 return 2 * numwords
;
2005 /* Return the cost of moving data of mode MODE between a register of class
2006 CLASS and memory. IN is zero if the value is to be written to memory,
2007 non-zero if it is to be read in. This cost is relative to those in
2008 visium_register_move_cost. */
2011 visium_memory_move_cost (machine_mode mode
,
2012 reg_class_t to ATTRIBUTE_UNUSED
,
2015 /* Moving data in can be from PROM and this is expensive. */
2018 if (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
)
2024 /* Moving data out is mostly to RAM and should be cheaper. */
2027 if (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
)
2034 /* Return the relative costs of expression X. */
2037 visium_rtx_costs (rtx x
, machine_mode mode
, int outer_code ATTRIBUTE_UNUSED
,
2038 int opno ATTRIBUTE_UNUSED
, int *total
,
2039 bool speed ATTRIBUTE_UNUSED
)
2041 int code
= GET_CODE (x
);
2046 /* Small integers are as cheap as registers. 4-byte values can
2047 be fetched as immediate constants - let's give that the cost
2048 of an extra insn. */
2049 *total
= COSTS_N_INSNS (!satisfies_constraint_J (x
));
2055 *total
= COSTS_N_INSNS (2);
2061 split_double (x
, &high
, &low
);
2064 (!satisfies_constraint_J (high
) + !satisfies_constraint_J (low
));
2069 *total
= COSTS_N_INSNS (3);
2077 *total
= COSTS_N_INSNS (64);
2079 *total
= COSTS_N_INSNS (32);
2085 /* DImode operations are performed directly on the ALU. */
2087 *total
= COSTS_N_INSNS (2);
2089 *total
= COSTS_N_INSNS (1);
2095 /* DImode operations are performed on the EAM instead. */
2097 *total
= COSTS_N_INSNS (3);
2099 *total
= COSTS_N_INSNS (1);
2103 /* This matches the btst pattern. */
2104 if (GET_CODE (XEXP (x
, 0)) == ZERO_EXTRACT
2105 && XEXP (x
, 1) == const0_rtx
2106 && XEXP (XEXP (x
, 0), 1) == const1_rtx
2107 && satisfies_constraint_K (XEXP (XEXP (x
, 0), 2)))
2108 *total
= COSTS_N_INSNS (1);
2116 /* Split a double move of OPERANDS in MODE. */
2119 visium_split_double_move (rtx
*operands
, machine_mode mode
)
2123 /* Check register to register with overlap. */
2124 if (GET_CODE (operands
[0]) == REG
2125 && GET_CODE (operands
[1]) == REG
2126 && REGNO (operands
[0]) == REGNO (operands
[1]) + 1)
2129 /* Check memory to register where the base reg overlaps the destination. */
2130 if (GET_CODE (operands
[0]) == REG
&& GET_CODE (operands
[1]) == MEM
)
2132 rtx op
= XEXP (operands
[1], 0);
2134 if (GET_CODE (op
) == SUBREG
)
2135 op
= SUBREG_REG (op
);
2137 if (GET_CODE (op
) == REG
&& REGNO (op
) == REGNO (operands
[0]))
2140 if (GET_CODE (op
) == PLUS
)
2142 rtx x
= XEXP (op
, 0);
2143 rtx y
= XEXP (op
, 1);
2145 if (GET_CODE (x
) == REG
&& REGNO (x
) == REGNO (operands
[0]))
2148 if (GET_CODE (y
) == REG
&& REGNO (y
) == REGNO (operands
[0]))
2155 operands
[2] = operand_subword (operands
[0], 1, 1, mode
);
2156 operands
[3] = operand_subword (operands
[1], 1, 1, mode
);
2157 operands
[4] = operand_subword (operands
[0], 0, 1, mode
);
2158 operands
[5] = operand_subword (operands
[1], 0, 1, mode
);
2162 operands
[2] = operand_subword (operands
[0], 0, 1, mode
);
2163 operands
[3] = operand_subword (operands
[1], 0, 1, mode
);
2164 operands
[4] = operand_subword (operands
[0], 1, 1, mode
);
2165 operands
[5] = operand_subword (operands
[1], 1, 1, mode
);
2169 /* Split a double addition or subtraction of operands. */
2172 visium_split_double_add (enum rtx_code code
, rtx op0
, rtx op1
, rtx op2
)
2174 rtx op3
= gen_lowpart (SImode
, op0
);
2175 rtx op4
= gen_lowpart (SImode
, op1
);
2177 rtx op6
= gen_highpart (SImode
, op0
);
2178 rtx op7
= (op1
== const0_rtx
? op1
: gen_highpart (SImode
, op1
));
2182 /* If operand #2 is a small constant, then its high part is null. */
2183 if (CONST_INT_P (op2
))
2185 HOST_WIDE_INT val
= INTVAL (op2
);
2189 code
= (code
== MINUS
? PLUS
: MINUS
);
2193 op5
= gen_int_mode (val
, SImode
);
2198 op5
= gen_lowpart (SImode
, op2
);
2199 op8
= gen_highpart (SImode
, op2
);
2202 if (op4
== const0_rtx
)
2203 pat
= gen_negsi2_insn_set_carry (op3
, op5
);
2204 else if (code
== MINUS
)
2205 pat
= gen_subsi3_insn_set_carry (op3
, op4
, op5
);
2207 pat
= gen_addsi3_insn_set_carry (op3
, op4
, op5
);
2210 /* This is the plus_[plus_]sltu_flags or minus_[minus_]sltu_flags pattern. */
2211 if (op8
== const0_rtx
)
2214 x
= gen_rtx_fmt_ee (code
, SImode
, op7
, op8
);
2215 flags
= gen_rtx_REG (CCCmode
, FLAGS_REGNUM
);
2216 x
= gen_rtx_fmt_ee (code
, SImode
, x
, gen_rtx_LTU (SImode
, flags
, const0_rtx
));
2217 pat
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (2));
2218 XVECEXP (pat
, 0, 0) = gen_rtx_SET (op6
, x
);
2219 flags
= gen_rtx_REG (CCmode
, FLAGS_REGNUM
);
2220 XVECEXP (pat
, 0, 1) = gen_rtx_CLOBBER (VOIDmode
, flags
);
2223 visium_flags_exposed
= true;
2226 /* Expand a copysign of OPERANDS in MODE. */
2229 visium_expand_copysign (rtx
*operands
, machine_mode mode
)
2231 rtx op0
= operands
[0];
2232 rtx op1
= operands
[1];
2233 rtx op2
= operands
[2];
2234 rtx mask
= force_reg (SImode
, GEN_INT (0x7fffffff));
2237 /* We manually handle SFmode because the abs and neg instructions of
2238 the FPU on the MCM have a non-standard behavior wrt NaNs. */
2239 gcc_assert (mode
== SFmode
);
2241 /* First get all the non-sign bits of op1. */
2242 if (GET_CODE (op1
) == CONST_DOUBLE
)
2244 if (real_isneg (CONST_DOUBLE_REAL_VALUE (op1
)))
2245 op1
= simplify_unary_operation (ABS
, mode
, op1
, mode
);
2246 if (op1
!= CONST0_RTX (mode
))
2249 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op1
), l
);
2250 op1
= force_reg (SImode
, gen_int_mode (l
, SImode
));
2255 op1
= copy_to_mode_reg (SImode
, gen_lowpart (SImode
, op1
));
2256 op1
= force_reg (SImode
, gen_rtx_AND (SImode
, op1
, mask
));
2259 /* Then get the sign bit of op2. */
2260 mask
= force_reg (SImode
, gen_rtx_NOT (SImode
, mask
));
2261 op2
= copy_to_mode_reg (SImode
, gen_lowpart (SImode
, op2
));
2262 op2
= force_reg (SImode
, gen_rtx_AND (SImode
, op2
, mask
));
2264 /* Finally OR the two values. */
2265 if (op1
== CONST0_RTX (SFmode
))
2268 x
= force_reg (SImode
, gen_rtx_IOR (SImode
, op1
, op2
));
2270 /* And move the result to the destination. */
2271 emit_insn (gen_rtx_SET (op0
, gen_lowpart (SFmode
, x
)));
2274 /* Expand a cstore of OPERANDS in MODE for EQ/NE/LTU/GTU/GEU/LEU. We generate
2275 the result in the C flag and use the ADC/SUBC instructions to write it into
2276 the destination register.
2278 It would also be possible to implement support for LT/GT/LE/GE by means of
2279 the RFLAG instruction followed by some shifts, but this can pessimize the
2283 visium_expand_int_cstore (rtx
*operands
, machine_mode mode
)
2285 enum rtx_code code
= GET_CODE (operands
[1]);
2286 rtx op0
= operands
[0], op1
= operands
[2], op2
= operands
[3], sltu
;
2287 bool reverse
= false;
2293 /* We use a special comparison to get the result in the C flag. */
2294 if (op2
!= const0_rtx
)
2295 op1
= force_reg (mode
, gen_rtx_XOR (mode
, op1
, op2
));
2296 op1
= gen_rtx_NOT (mode
, op1
);
2304 /* The result is naturally in the C flag modulo a couple of tricks. */
2305 code
= reverse_condition (code
);
2308 /* ... fall through ... */
2324 /* We need either a single ADC or a SUBC and a PLUS. */
2325 sltu
= gen_rtx_LTU (SImode
, op1
, op2
);
2329 rtx tmp
= copy_to_mode_reg (SImode
, gen_rtx_NEG (SImode
, sltu
));
2330 emit_insn (gen_add3_insn (op0
, tmp
, const1_rtx
));
2333 emit_insn (gen_rtx_SET (op0
, sltu
));
2336 /* Expand a cstore of OPERANDS in MODE for LT/GT/UNGE/UNLE. We generate the
2337 result in the C flag and use the ADC/SUBC instructions to write it into
2338 the destination register. */
2341 visium_expand_fp_cstore (rtx
*operands
,
2342 machine_mode mode ATTRIBUTE_UNUSED
)
2344 enum rtx_code code
= GET_CODE (operands
[1]);
2345 rtx op0
= operands
[0], op1
= operands
[2], op2
= operands
[3], slt
;
2346 bool reverse
= false;
2352 /* The result is naturally in the C flag modulo a couple of tricks. */
2353 code
= reverse_condition_maybe_unordered (code
);
2356 /* ... fall through ... */
2372 /* We need either a single ADC or a SUBC and a PLUS. */
2373 slt
= gen_rtx_LT (SImode
, op1
, op2
);
2377 rtx tmp
= copy_to_mode_reg (SImode
, gen_rtx_NEG (SImode
, slt
));
2378 emit_insn (gen_add3_insn (op0
, tmp
, const1_rtx
));
2381 emit_insn (gen_rtx_SET (op0
, slt
));
2384 /* Split a compare-and-store with CODE, operands OP2 and OP3, combined with
2385 operation with OP_CODE, operands OP0 and OP1. */
2388 visium_split_cstore (enum rtx_code op_code
, rtx op0
, rtx op1
,
2389 enum rtx_code code
, rtx op2
, rtx op3
)
2391 machine_mode cc_mode
= visium_select_cc_mode (code
, op2
, op3
);
2393 /* If a FP cstore was reversed, then it was originally UNGE/UNLE. */
2394 if (cc_mode
== CCFPEmode
&& (op_code
== NEG
|| op_code
== MINUS
))
2397 rtx flags
= gen_rtx_REG (cc_mode
, FLAGS_REGNUM
);
2398 rtx x
= gen_rtx_COMPARE (cc_mode
, op2
, op3
);
2399 x
= gen_rtx_SET (flags
, x
);
2402 x
= gen_rtx_fmt_ee (code
, SImode
, flags
, const0_rtx
);
2408 x
= gen_rtx_NEG (SImode
, x
);
2412 x
= gen_rtx_fmt_ee (op_code
, SImode
, op1
, x
);
2418 rtx pat
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (2));
2419 XVECEXP (pat
, 0, 0) = gen_rtx_SET (op0
, x
);
2420 flags
= gen_rtx_REG (CCmode
, FLAGS_REGNUM
);
2421 XVECEXP (pat
, 0, 1) = gen_rtx_CLOBBER (VOIDmode
, flags
);
2424 visium_flags_exposed
= true;
2427 /* Generate a call to a library function to move BYTES_RTX bytes from SRC with
2428 address SRC_REG to DST with address DST_REG in 4-byte chunks. */
2431 expand_block_move_4 (rtx dst
, rtx dst_reg
, rtx src
, rtx src_reg
, rtx bytes_rtx
)
2433 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2434 unsigned int rem
= bytes
% 4;
2441 emit_move_insn (regno_reg_rtx
[1], dst_reg
);
2442 emit_move_insn (regno_reg_rtx
[2], src_reg
);
2443 emit_move_insn (regno_reg_rtx
[3], bytes_rtx
);
2445 insn
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (8));
2446 XVECEXP (insn
, 0, 0)
2447 = gen_rtx_SET (replace_equiv_address_nv (dst
, regno_reg_rtx
[1]),
2448 replace_equiv_address_nv (src
, regno_reg_rtx
[2]));
2449 XVECEXP (insn
, 0, 1) = gen_rtx_USE (VOIDmode
, regno_reg_rtx
[3]);
2450 for (i
= 1; i
<= 6; i
++)
2451 XVECEXP (insn
, 0, 1 + i
)
2452 = gen_rtx_CLOBBER (VOIDmode
, regno_reg_rtx
[i
]);
2456 emit_library_call (long_int_memcpy_libfunc
, LCT_NORMAL
, VOIDmode
,
2459 convert_to_mode (TYPE_MODE (sizetype
),
2460 GEN_INT (bytes
>> 2),
2461 TYPE_UNSIGNED (sizetype
)),
2462 TYPE_MODE (sizetype
));
2466 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2467 src
= replace_equiv_address_nv (src
, src_reg
);
2472 emit_move_insn (adjust_address_nv (dst
, HImode
, bytes
),
2473 adjust_address_nv (src
, HImode
, bytes
));
2479 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2480 adjust_address_nv (src
, QImode
, bytes
));
2483 /* Generate a call to a library function to move BYTES_RTX bytes from SRC with
2484 address SRC_REG to DST with address DST_REG in 2-bytes chunks. */
2487 expand_block_move_2 (rtx dst
, rtx dst_reg
, rtx src
, rtx src_reg
, rtx bytes_rtx
)
2489 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2490 unsigned int rem
= bytes
% 2;
2492 emit_library_call (wrd_memcpy_libfunc
, LCT_NORMAL
, VOIDmode
,
2495 convert_to_mode (TYPE_MODE (sizetype
),
2496 GEN_INT (bytes
>> 1),
2497 TYPE_UNSIGNED (sizetype
)),
2498 TYPE_MODE (sizetype
));
2502 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2503 src
= replace_equiv_address_nv (src
, src_reg
);
2506 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2507 adjust_address_nv (src
, QImode
, bytes
));
2510 /* Generate a call to a library function to move BYTES_RTX bytes from address
2511 SRC_REG to address DST_REG in 1-byte chunks. */
2514 expand_block_move_1 (rtx dst_reg
, rtx src_reg
, rtx bytes_rtx
)
2516 emit_library_call (byt_memcpy_libfunc
, LCT_NORMAL
, VOIDmode
,
2519 convert_to_mode (TYPE_MODE (sizetype
),
2521 TYPE_UNSIGNED (sizetype
)),
2522 TYPE_MODE (sizetype
));
2525 /* Generate a call to a library function to set BYTES_RTX bytes of DST with
2526 address DST_REG to VALUE_RTX in 4-byte chunks. */
2529 expand_block_set_4 (rtx dst
, rtx dst_reg
, rtx value_rtx
, rtx bytes_rtx
)
2531 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2532 unsigned int rem
= bytes
% 4;
2534 value_rtx
= convert_to_mode (Pmode
, value_rtx
, 1);
2535 emit_library_call (long_int_memset_libfunc
, LCT_NORMAL
, VOIDmode
,
2538 convert_to_mode (TYPE_MODE (sizetype
),
2539 GEN_INT (bytes
>> 2),
2540 TYPE_UNSIGNED (sizetype
)),
2541 TYPE_MODE (sizetype
));
2545 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2550 if (CONST_INT_P (value_rtx
))
2552 const unsigned HOST_WIDE_INT value
= UINTVAL (value_rtx
) & 0xff;
2553 emit_move_insn (adjust_address_nv (dst
, HImode
, bytes
),
2554 gen_int_mode ((value
<< 8) | value
, HImode
));
2558 rtx temp
= convert_to_mode (QImode
, value_rtx
, 1);
2559 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
), temp
);
2560 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
+ 1), temp
);
2567 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2568 convert_to_mode (QImode
, value_rtx
, 1));
2571 /* Generate a call to a library function to set BYTES_RTX bytes of DST with
2572 address DST_REG to VALUE_RTX in 2-byte chunks. */
2575 expand_block_set_2 (rtx dst
, rtx dst_reg
, rtx value_rtx
, rtx bytes_rtx
)
2577 unsigned HOST_WIDE_INT bytes
= UINTVAL (bytes_rtx
);
2578 unsigned int rem
= bytes
% 2;
2580 value_rtx
= convert_to_mode (Pmode
, value_rtx
, 1);
2581 emit_library_call (wrd_memset_libfunc
, LCT_NORMAL
, VOIDmode
,
2584 convert_to_mode (TYPE_MODE (sizetype
),
2585 GEN_INT (bytes
>> 1),
2586 TYPE_UNSIGNED (sizetype
)),
2587 TYPE_MODE (sizetype
));
2591 dst
= replace_equiv_address_nv (dst
, dst_reg
);
2594 emit_move_insn (adjust_address_nv (dst
, QImode
, bytes
),
2595 convert_to_mode (QImode
, value_rtx
, 1));
2598 /* Generate a call to a library function to set BYTES_RTX bytes at address
2599 DST_REG to VALUE_RTX in 1-byte chunks. */
2602 expand_block_set_1 (rtx dst_reg
, rtx value_rtx
, rtx bytes_rtx
)
2604 value_rtx
= convert_to_mode (Pmode
, value_rtx
, 1);
2605 emit_library_call (byt_memset_libfunc
, LCT_NORMAL
, VOIDmode
,
2608 convert_to_mode (TYPE_MODE (sizetype
),
2610 TYPE_UNSIGNED (sizetype
)),
2611 TYPE_MODE (sizetype
));
2614 /* Expand string/block move operations.
2616 operands[0] is the pointer to the destination.
2617 operands[1] is the pointer to the source.
2618 operands[2] is the number of bytes to move.
2619 operands[3] is the alignment.
2621 Return 1 upon success, 0 otherwise. */
2624 visium_expand_block_move (rtx
*operands
)
2626 rtx dst
= operands
[0];
2627 rtx src
= operands
[1];
2628 rtx bytes_rtx
= operands
[2];
2629 rtx align_rtx
= operands
[3];
2630 const int align
= INTVAL (align_rtx
);
2631 rtx dst_reg
, src_reg
;
2632 tree dst_expr
, src_expr
;
2634 /* We only handle a fixed number of bytes for now. */
2635 if (!CONST_INT_P (bytes_rtx
) || INTVAL (bytes_rtx
) <= 0)
2638 /* Copy the addresses into scratch registers. */
2639 dst_reg
= copy_addr_to_reg (XEXP (dst
, 0));
2640 src_reg
= copy_addr_to_reg (XEXP (src
, 0));
2642 /* Move the data with the appropriate granularity. */
2644 expand_block_move_4 (dst
, dst_reg
, src
, src_reg
, bytes_rtx
);
2645 else if (align
>= 2)
2646 expand_block_move_2 (dst
, dst_reg
, src
, src_reg
, bytes_rtx
);
2648 expand_block_move_1 (dst_reg
, src_reg
, bytes_rtx
);
2650 /* Since DST and SRC are passed to a libcall, mark the corresponding
2651 tree EXPR as addressable. */
2652 dst_expr
= MEM_EXPR (dst
);
2653 src_expr
= MEM_EXPR (src
);
2655 mark_addressable (dst_expr
);
2657 mark_addressable (src_expr
);
2662 /* Expand string/block set operations.
2664 operands[0] is the pointer to the destination.
2665 operands[1] is the number of bytes to set.
2666 operands[2] is the source value.
2667 operands[3] is the alignment.
2669 Return 1 upon success, 0 otherwise. */
2672 visium_expand_block_set (rtx
*operands
)
2674 rtx dst
= operands
[0];
2675 rtx bytes_rtx
= operands
[1];
2676 rtx value_rtx
= operands
[2];
2677 rtx align_rtx
= operands
[3];
2678 const int align
= INTVAL (align_rtx
);
2682 /* We only handle a fixed number of bytes for now. */
2683 if (!CONST_INT_P (bytes_rtx
) || INTVAL (bytes_rtx
) <= 0)
2686 /* Copy the address into a scratch register. */
2687 dst_reg
= copy_addr_to_reg (XEXP (dst
, 0));
2689 /* Set the data with the appropriate granularity. */
2691 expand_block_set_4 (dst
, dst_reg
, value_rtx
, bytes_rtx
);
2692 else if (align
>= 2)
2693 expand_block_set_2 (dst
, dst_reg
, value_rtx
, bytes_rtx
);
2695 expand_block_set_1 (dst_reg
, value_rtx
, bytes_rtx
);
2697 /* Since DST is passed to a libcall, mark the corresponding
2698 tree EXPR as addressable. */
2699 dst_expr
= MEM_EXPR (dst
);
2701 mark_addressable (dst_expr
);
2706 /* Initialize a trampoline. M_TRAMP is an RTX for the memory block for the
2707 trampoline, FNDECL is the FUNCTION_DECL for the nested function and
2708 STATIC_CHAIN is an RTX for the static chain value that should be passed
2709 to the function when it is called. */
2712 visium_trampoline_init (rtx m_tramp
, tree fndecl
, rtx static_chain
)
2714 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2715 rtx addr
= XEXP (m_tramp
, 0);
2717 /* The trampoline initialization sequence is:
2719 moviu r9,%u FUNCTION
2720 movil r9,%l FUNCTION
2725 We don't use r0 as the destination register of the branch because we want
2726 the Branch Pre-decode Logic of the GR6 to use the Address Load Array to
2727 predict the branch target. */
2729 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 0)),
2730 plus_constant (SImode
,
2731 expand_shift (RSHIFT_EXPR
, SImode
, fnaddr
,
2735 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 4)),
2736 plus_constant (SImode
,
2737 expand_and (SImode
, fnaddr
, GEN_INT (0xffff),
2741 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 8)),
2742 plus_constant (SImode
,
2743 expand_shift (RSHIFT_EXPR
, SImode
,
2748 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 12)),
2749 gen_int_mode (0xff892404, SImode
));
2751 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, addr
, 16)),
2752 plus_constant (SImode
,
2753 expand_and (SImode
, static_chain
,
2754 GEN_INT (0xffff), NULL_RTX
),
2757 emit_library_call (set_trampoline_parity_libfunc
, LCT_NORMAL
, VOIDmode
,
2761 /* Return true if the current function must have and use a frame pointer. */
2764 visium_frame_pointer_required (void)
2766 /* The frame pointer is required if the function isn't leaf to be able to
2767 do manual stack unwinding. */
2771 /* If the stack pointer is dynamically modified in the function, it cannot
2772 serve as the frame pointer. */
2773 if (!crtl
->sp_is_unchanging
)
2776 /* If the function receives nonlocal gotos, it needs to save the frame
2777 pointer in the nonlocal_goto_save_area object. */
2778 if (cfun
->has_nonlocal_label
)
2781 /* The frame also needs to be established in some special cases. */
2782 if (visium_frame_needed
)
2788 /* Profiling support. Just a call to MCOUNT is needed. No labelled counter
2789 location is involved. Proper support for __builtin_return_address is also
2790 required, which is fairly straightforward provided a frame gets created. */
2793 visium_profile_hook (void)
2795 visium_frame_needed
= true;
2796 emit_library_call (gen_rtx_SYMBOL_REF (Pmode
, "mcount"), LCT_NORMAL
,
2800 /* A C expression whose value is RTL representing the address in a stack frame
2801 where the pointer to the caller's frame is stored. Assume that FRAMEADDR is
2802 an RTL expression for the address of the stack frame itself.
2804 If you don't define this macro, the default is to return the value of
2805 FRAMEADDR--that is, the stack frame address is also the address of the stack
2806 word that points to the previous frame. */
2809 visium_dynamic_chain_address (rtx frame
)
2811 /* This is the default, but we need to make sure the frame gets created. */
2812 visium_frame_needed
= true;
2816 /* A C expression whose value is RTL representing the value of the return
2817 address for the frame COUNT steps up from the current frame, after the
2818 prologue. FRAMEADDR is the frame pointer of the COUNT frame, or the frame
2819 pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' is
2822 The value of the expression must always be the correct address when COUNT is
2823 zero, but may be `NULL_RTX' if there is not way to determine the return
2824 address of other frames. */
2827 visium_return_addr_rtx (int count
, rtx frame ATTRIBUTE_UNUSED
)
2829 /* Dont try to compute anything other than frame zero. */
2833 visium_frame_needed
= true;
2835 gen_frame_mem (Pmode
, plus_constant (Pmode
, hard_frame_pointer_rtx
, 4));
2838 /* Helper function for EH_RETURN_HANDLER_RTX. Return the RTX representing a
2839 location in which to store the address of an exception handler to which we
2843 visium_eh_return_handler_rtx (void)
2846 = gen_frame_mem (SImode
, plus_constant (Pmode
, hard_frame_pointer_rtx
, 4));
2847 MEM_VOLATILE_P (mem
) = 1;
2851 static struct machine_function
*
2852 visium_init_machine_status (void)
2854 return ggc_cleared_alloc
<machine_function
> ();
2857 /* The per-function data machinery is needed to indicate when a frame
2861 visium_init_expanders (void)
2863 init_machine_status
= visium_init_machine_status
;
2866 /* Given a comparison code (EQ, NE, etc.) and the operands of a COMPARE,
2867 return the mode to be used for the comparison. */
2870 visium_select_cc_mode (enum rtx_code code
, rtx op0
, rtx op1
)
2872 if (GET_MODE_CLASS (GET_MODE (op0
)) == MODE_FLOAT
)
2892 /* These 2 comparison codes are not supported. */
2900 /* This is for the cmp<mode>_sne pattern. */
2901 if (op1
== constm1_rtx
)
2904 /* This is for the add<mode>3_insn_set_carry pattern. */
2905 if ((code
== LTU
|| code
== GEU
)
2906 && GET_CODE (op0
) == PLUS
2907 && rtx_equal_p (XEXP (op0
, 0), op1
))
2910 /* This is for the {add,sub,neg}<mode>3_insn_set_overflow pattern. */
2911 if ((code
== EQ
|| code
== NE
)
2912 && GET_CODE (op1
) == UNSPEC
2913 && (XINT (op1
, 1) == UNSPEC_ADDV
2914 || XINT (op1
, 1) == UNSPEC_SUBV
2915 || XINT (op1
, 1) == UNSPEC_NEGV
))
2918 if (op1
!= const0_rtx
)
2921 switch (GET_CODE (op0
))
2929 /* The C and V flags may be set differently from a COMPARE with zero.
2930 The consequence is that a comparison operator testing C or V must
2931 be turned into another operator not testing C or V and yielding
2932 the same result for a comparison with zero. That's possible for
2933 GE/LT which become NC/NS respectively, but not for GT/LE for which
2934 the altered operator doesn't exist on the Visium. */
2938 /* This is a btst, the result is in C instead of Z. */
2950 /* Pretend that the flags are set as for a COMPARE with zero.
2951 That's mostly true, except for the 2 right shift insns that
2952 will set the C flag. But the C flag is relevant only for
2953 the unsigned comparison operators and they are eliminated
2954 when applied to a comparison with zero. */
2957 /* ??? Cater to the junk RTXes sent by try_merge_compare. */
2973 /* Split a compare-and-branch with CODE, operands OP0 and OP1, and LABEL. */
2976 visium_split_cbranch (enum rtx_code code
, rtx op0
, rtx op1
, rtx label
)
2978 machine_mode cc_mode
= visium_select_cc_mode (code
, op0
, op1
);
2979 rtx flags
= gen_rtx_REG (cc_mode
, FLAGS_REGNUM
);
2981 rtx x
= gen_rtx_COMPARE (cc_mode
, op0
, op1
);
2982 x
= gen_rtx_SET (flags
, x
);
2985 x
= gen_rtx_fmt_ee (code
, VOIDmode
, flags
, const0_rtx
);
2986 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
, gen_rtx_LABEL_REF (Pmode
, label
),
2988 x
= gen_rtx_SET (pc_rtx
, x
);
2991 visium_flags_exposed
= true;
2994 /* Branch instructions on the Visium.
2996 Setting aside the interrupt-handling specific instructions, the ISA has
2997 two branch instructions: BRR and BRA. The former is used to implement
2998 short branches (+/- 2^17) within functions and its target is encoded in
2999 the instruction. The latter is used to implement all the other types
3000 of control flow changes and its target might not be statically known
3001 or even easily predictable at run time. Here's a complete summary of
3002 the patterns that generate a BRA instruction:
3012 Among these patterns, only the return (5) and the long branch (6) can be
3013 conditional; all the other patterns are always unconditional.
3015 The following algorithm can be used to identify the pattern for which
3016 the BRA instruction was generated and work out its target:
3018 A. If the source is r21 and the destination is r0, this is a return (5)
3019 and the target is the caller (i.e. the value of r21 on function's
3022 B. If the source is rN, N != 21 and the destination is r0, this is either
3023 an indirect jump or a table jump (1, 2) and the target is not easily
3026 C. If the source is rN, N != 21 and the destination is r21, this is a call
3027 (3) and the target is given by the preceding MOVIL/MOVIU pair for rN,
3028 unless this is an indirect call in which case the target is not easily
3031 D. If the source is rN, N != 21 and the destination is also rN, this is
3032 either a sibling call or a trampoline (4, 7) and the target is given
3033 by the preceding MOVIL/MOVIU pair for rN.
3035 E. If the source is r21 and the destination is also r21, this is a long
3036 branch (6) and the target is given by the preceding MOVIL/MOVIU pair
3039 The other combinations are not used. This implementation has been devised
3040 to accommodate the branch predictor of the GR6 but is used unconditionally
3041 by the compiler, i.e. including for earlier processors. */
3043 /* Output a conditional/unconditional branch to LABEL. COND is the string
3044 condition. INSN is the instruction. */
3047 output_branch (rtx label
, const char *cond
, rtx_insn
*insn
)
3053 operands
[0] = label
;
3055 /* If the length of the instruction is greater than 8, then this is a
3056 long branch and we need to work harder to emit it properly. */
3057 if (get_attr_length (insn
) > 8)
3061 /* If the link register has been saved, then we use it. */
3062 if (current_function_saves_lr ())
3064 operands
[1] = regno_reg_rtx
[LINK_REGNUM
];
3068 /* Or else, if the long-branch register isn't live, we use it. */
3069 else if (!df_regs_ever_live_p (long_branch_regnum
))
3071 operands
[1] = regno_reg_rtx
[long_branch_regnum
];
3075 /* Otherwise, we will use the long-branch register but we need to
3076 spill it to the stack and reload it at the end. We should have
3077 reserved the LR slot for this purpose. */
3080 operands
[1] = regno_reg_rtx
[long_branch_regnum
];
3082 gcc_assert (current_function_has_lr_slot ());
3085 /* First emit the spill to the stack:
3088 write.l [1](sp),reg */
3093 rtx_insn
*delay
= NEXT_INSN (insn
);
3097 final_scan_insn (delay
, asm_out_file
, optimize
, 0, &seen
);
3098 PATTERN (delay
) = gen_blockage ();
3099 INSN_CODE (delay
) = -1;
3102 if (current_function_saves_fp ())
3103 output_asm_insn ("write.l 1(sp),%1", operands
);
3105 output_asm_insn ("write.l (sp),%1", operands
);
3108 /* Then emit the core sequence:
3114 We don't use r0 as the destination register of the branch because we
3115 want the Branch Pre-decode Logic of the GR6 to use the Address Load
3116 Array to predict the branch target. */
3117 output_asm_insn ("moviu %1,%%u %0", operands
);
3118 output_asm_insn ("movil %1,%%l %0", operands
);
3119 strcpy (str
, "bra ");
3121 strcat (str
, ",%1,%1");
3124 strcat (str
, "\t\t;long branch");
3125 output_asm_insn (str
, operands
);
3127 /* Finally emit the reload:
3129 read.l reg,[1](sp) */
3132 if (current_function_saves_fp ())
3133 output_asm_insn (" read.l %1,1(sp)", operands
);
3135 output_asm_insn (" read.l %1,(sp)", operands
);
3139 /* Or else, if the label is PC, then this is a return. */
3140 else if (label
== pc_rtx
)
3142 strcpy (str
, "bra ");
3144 strcat (str
, ",r21,r0%#\t\t;return");
3145 output_asm_insn (str
, operands
);
3148 /* Otherwise, this is a short branch. */
3151 strcpy (str
, "brr ");
3153 strcat (str
, ",%0%#");
3154 output_asm_insn (str
, operands
);
3160 /* Output an unconditional branch to LABEL. INSN is the instruction. */
3163 output_ubranch (rtx label
, rtx_insn
*insn
)
3165 return output_branch (label
, "tr", insn
);
3168 /* Output a conditional branch to LABEL. CODE is the comparison code.
3169 CC_MODE is the mode of the CC register. REVERSED is non-zero if we
3170 should reverse the sense of the comparison. INSN is the instruction. */
3173 output_cbranch (rtx label
, enum rtx_code code
, machine_mode cc_mode
,
3174 int reversed
, rtx_insn
*insn
)
3180 if (cc_mode
== CCFPmode
|| cc_mode
== CCFPEmode
)
3181 code
= reverse_condition_maybe_unordered (code
);
3183 code
= reverse_condition (code
);
3189 if (cc_mode
== CCCmode
)
3191 else if (cc_mode
== CCVmode
)
3198 if (cc_mode
== CCCmode
)
3200 else if (cc_mode
== CCVmode
)
3207 if (cc_mode
== CCNZmode
)
3218 if (cc_mode
== CCFPmode
|| cc_mode
== CCFPEmode
)
3225 if (cc_mode
== CCFPmode
|| cc_mode
== CCFPEmode
)
3226 cond
= "cs"; /* or "ns" */
3227 else if (cc_mode
== CCNZmode
)
3258 cond
= "cc"; /* or "nc" */
3273 /* These 2 comparison codes are not supported. */
3280 return output_branch (label
, cond
, insn
);
3283 /* Implement TARGET_PRINT_OPERAND_PUNCT_VALID_P. */
3286 visium_print_operand_punct_valid_p (unsigned char code
)
3291 /* Implement TARGET_PRINT_OPERAND. Output to stdio stream FILE the assembler
3292 syntax for an instruction operand OP subject to the modifier LETTER. */
3295 visium_print_operand (FILE *file
, rtx op
, int letter
)
3300 /* Output an insn in a delay slot. */
3302 visium_indent_opcode
= 1;
3304 fputs ("\n\t nop", file
);
3308 /* Print LS 8 bits of operand. */
3309 fprintf (file
, HOST_WIDE_INT_PRINT_UNSIGNED
, UINTVAL (op
) & 0xff);
3313 /* Print LS 16 bits of operand. */
3314 fprintf (file
, HOST_WIDE_INT_PRINT_UNSIGNED
, UINTVAL (op
) & 0xffff);
3318 /* Print MS 16 bits of operand. */
3320 HOST_WIDE_INT_PRINT_UNSIGNED
, (UINTVAL (op
) >> 16) & 0xffff);
3324 /* It's either a register or zero. */
3325 if (GET_CODE (op
) == REG
)
3326 fputs (reg_names
[REGNO (op
)], file
);
3328 fputs (reg_names
[0], file
);
3332 /* It's either a FP register or zero. */
3333 if (GET_CODE (op
) == REG
)
3334 fputs (reg_names
[REGNO (op
)], file
);
3336 fputs (reg_names
[FP_FIRST_REGNUM
], file
);
3340 switch (GET_CODE (op
))
3344 fputs (reg_names
[REGNO (op
) + 1], file
);
3346 fputs (reg_names
[REGNO (op
)], file
);
3352 output_addr_const (file
, op
);
3356 visium_print_operand_address (file
, GET_MODE (op
), XEXP (op
, 0));
3360 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (op
));
3364 asm_fprintf (file
, "%LL%d", CODE_LABEL_NUMBER (op
));
3368 visium_print_operand (file
, XEXP (op
, 1), letter
);
3372 fatal_insn ("illegal operand ", op
);
3376 /* Implement TARGET_PRINT_OPERAND_ADDRESS. Output to stdio stream FILE the
3377 assembler syntax for an instruction operand that is a memory reference
3378 whose address is ADDR. */
3381 visium_print_operand_address (FILE *file
, machine_mode mode
, rtx addr
)
3383 switch (GET_CODE (addr
))
3387 fprintf (file
, "(%s)", reg_names
[true_regnum (addr
)]);
3392 rtx x
= XEXP (addr
, 0), y
= XEXP (addr
, 1);
3394 switch (GET_CODE (x
))
3398 if (CONST_INT_P (y
))
3400 unsigned int regno
= true_regnum (x
);
3401 HOST_WIDE_INT val
= INTVAL (y
);
3419 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
"(%s)", val
,
3423 fatal_insn ("illegal operand address (1)", addr
);
3427 if (CONSTANT_P (x
) && CONSTANT_P (y
))
3428 output_addr_const (file
, addr
);
3430 fatal_insn ("illegal operand address (2)", addr
);
3440 output_addr_const (file
, addr
);
3444 if (NOTE_KIND (addr
) != NOTE_INSN_DELETED_LABEL
)
3445 fatal_insn ("illegal operand address (3)", addr
);
3449 asm_fprintf (file
, "%LL%d", CODE_LABEL_NUMBER (addr
));
3453 fatal_insn ("illegal operand address (4)", addr
);
3458 /* The Visium stack frames look like:
3460 Before call After call
3461 +-----------------------+ +-----------------------+
3463 high | previous | | previous |
3464 mem | frame | | frame |
3466 +-----------------------+ +-----------------------+
3468 | arguments on stack | | arguments on stack |
3470 SP+0->+-----------------------+ +-----------------------+
3471 | reg parm save area, |
3472 | only created for |
3473 | variable argument |
3475 +-----------------------+
3477 | register save area |
3479 +-----------------------+
3483 FP+8->+-----------------------+
3485 FP+4->+-----------------------+
3487 FP+0->+-----------------------+
3489 | alloca allocations |
3491 +-----------------------+
3493 low | arguments on stack |
3495 SP+0->+-----------------------+
3498 1) The "reg parm save area" does not exist for non variable argument fns.
3499 2) The FP register is not saved if `frame_pointer_needed' is zero and it
3500 is not altered in the current function.
3501 3) The return address is not saved if there is no frame pointer and the
3502 current function is leaf.
3503 4) If the return address is not saved and the static chain register is
3504 live in the function, we allocate the return address slot to be able
3505 to spill the register for a long branch. */
3507 /* Define the register classes for local purposes. */
3508 enum reg_type
{ general
, mdb
, mdc
, floating
, last_type
};
3510 #define GET_REG_TYPE(regno) \
3511 (GP_REGISTER_P (regno) ? general : \
3512 (regno) == MDB_REGNUM ? mdb : \
3513 (regno) == MDC_REGNUM ? mdc : \
3516 /* First regno of each register type. */
3517 const int first_regno
[last_type
] = {0, MDB_REGNUM
, MDC_REGNUM
, FP_FIRST_REGNUM
};
3519 /* Size in bytes of each register type. */
3520 const int reg_type_size
[last_type
] = {4, 8, 4, 4};
3522 /* Structure to be filled in by visium_compute_frame_size. */
3523 struct visium_frame_info
3525 unsigned int save_area_size
; /* # bytes in the reg parm save area. */
3526 unsigned int reg_size1
; /* # bytes to store first block of regs. */
3527 unsigned int reg_size2
; /* # bytes to store second block of regs. */
3528 unsigned int max_reg1
; /* max. regno in first block */
3529 unsigned int var_size
; /* # bytes that variables take up. */
3530 unsigned int save_fp
; /* Nonzero if fp must be saved. */
3531 unsigned int save_lr
; /* Nonzero if lr must be saved. */
3532 unsigned int lr_slot
; /* Nonzero if the lr slot is needed. */
3533 unsigned int combine
; /* Nonzero if we can combine the allocation of
3534 variables and regs. */
3535 unsigned int interrupt
; /* Nonzero if the function is an interrupt
3537 unsigned int mask
[last_type
]; /* Masks of saved regs: gp, mdb, mdc, fp */
3540 /* Current frame information calculated by visium_compute_frame_size. */
3541 static struct visium_frame_info current_frame_info
;
3543 /* Accessor for current_frame_info.save_fp. */
3546 current_function_saves_fp (void)
3548 return current_frame_info
.save_fp
!= 0;
3551 /* Accessor for current_frame_info.save_lr. */
3554 current_function_saves_lr (void)
3556 return current_frame_info
.save_lr
!= 0;
3559 /* Accessor for current_frame_info.lr_slot. */
3562 current_function_has_lr_slot (void)
3564 return current_frame_info
.lr_slot
!= 0;
3567 /* Return non-zero if register REGNO needs to be saved in the frame. */
3570 visium_save_reg_p (int interrupt
, int regno
)
3574 case HARD_FRAME_POINTER_REGNUM
:
3575 /* This register is call-saved but handled specially. */
3579 /* This register is fixed but can be modified. */
3584 /* These registers are fixed and hold the interrupt context. */
3585 return (interrupt
!= 0);
3588 /* The other fixed registers are either immutable or special. */
3589 if (fixed_regs
[regno
])
3598 if (df_regs_ever_live_p (regno
))
3601 else if (call_used_regs
[regno
])
3604 /* To save mdb requires two temporary registers. To save mdc or
3605 any of the floating registers requires one temporary
3606 register. If this is an interrupt routine, the temporary
3607 registers need to be saved as well. These temporary registers
3608 are call used, so we only need deal with the case of leaf
3610 if (regno
== PROLOGUE_TMP_REGNUM
)
3612 if (df_regs_ever_live_p (MDB_REGNUM
)
3613 || df_regs_ever_live_p (MDC_REGNUM
))
3616 for (int i
= FP_FIRST_REGNUM
; i
<= FP_LAST_REGNUM
; i
++)
3617 if (df_regs_ever_live_p (i
))
3621 else if (regno
== PROLOGUE_TMP_REGNUM
+ 1)
3623 if (df_regs_ever_live_p (MDB_REGNUM
))
3628 return df_regs_ever_live_p (regno
) && !call_used_regs
[regno
];
3631 /* Compute the frame size required by the function. This function is called
3632 during the reload pass and also by visium_expand_prologue. */
3635 visium_compute_frame_size (int size
)
3637 const int save_area_size
= visium_reg_parm_save_area_size
;
3638 const int var_size
= VISIUM_STACK_ALIGN (size
);
3640 = frame_pointer_needed
|| df_regs_ever_live_p (HARD_FRAME_POINTER_REGNUM
);
3641 const int save_lr
= frame_pointer_needed
|| !crtl
->is_leaf
;
3642 const int lr_slot
= !save_lr
&& df_regs_ever_live_p (long_branch_regnum
);
3643 const int local_frame_offset
3644 = (save_fp
+ save_lr
+ lr_slot
) * UNITS_PER_WORD
;
3645 const int interrupt
= visium_interrupt_function_p ();
3646 unsigned int mask
[last_type
];
3655 memset (mask
, 0, last_type
* sizeof (unsigned int));
3657 /* The registers may need stacking in 2 blocks since only 32 32-bit words
3658 can be indexed from a given base address. */
3659 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
3661 if (visium_save_reg_p (interrupt
, regno
))
3663 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3664 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3665 int nbytes
= reg_type_size
[reg_type
];
3667 if (reg_size1
+ nbytes
> 32 * UNITS_PER_WORD
)
3670 reg_size1
+= nbytes
;
3672 mask
[reg_type
] |= mask_bit
;
3676 for (regno
= max_reg1
+ 1; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
3678 if (visium_save_reg_p (interrupt
, regno
))
3680 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3681 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3682 int nbytes
= reg_type_size
[reg_type
];
3684 reg_size2
+= nbytes
;
3685 mask
[reg_type
] |= mask_bit
;
3689 reg_size
= reg_size2
? reg_size2
: reg_size1
;
3690 combine
= (local_frame_offset
+ var_size
+ reg_size
) <= 32 * UNITS_PER_WORD
;
3692 = local_frame_offset
+ var_size
+ reg_size2
+ reg_size1
+ save_area_size
;
3694 current_frame_info
.save_area_size
= save_area_size
;
3695 current_frame_info
.reg_size1
= reg_size1
;
3696 current_frame_info
.max_reg1
= max_reg1
;
3697 current_frame_info
.reg_size2
= reg_size2
;
3698 current_frame_info
.var_size
= var_size
;
3699 current_frame_info
.save_fp
= save_fp
;
3700 current_frame_info
.save_lr
= save_lr
;
3701 current_frame_info
.lr_slot
= lr_slot
;
3702 current_frame_info
.combine
= combine
;
3703 current_frame_info
.interrupt
= interrupt
;
3705 memcpy (current_frame_info
.mask
, mask
, last_type
* sizeof (unsigned int));
3710 /* Helper function for INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET). Define
3711 the offset between two registers, one to be eliminated, and the other its
3712 replacement, at the start of a routine. */
3715 visium_initial_elimination_offset (int from
, int to ATTRIBUTE_UNUSED
)
3717 const int save_fp
= current_frame_info
.save_fp
;
3718 const int save_lr
= current_frame_info
.save_lr
;
3719 const int lr_slot
= current_frame_info
.lr_slot
;
3722 if (from
== FRAME_POINTER_REGNUM
)
3723 offset
= (save_fp
+ save_lr
+ lr_slot
) * UNITS_PER_WORD
;
3724 else if (from
== ARG_POINTER_REGNUM
)
3725 offset
= visium_compute_frame_size (get_frame_size ());
3732 /* For an interrupt handler, we may be saving call-clobbered registers.
3733 Say the epilogue uses these in addition to the link register. */
3736 visium_epilogue_uses (int regno
)
3738 if (regno
== LINK_REGNUM
)
3741 if (reload_completed
)
3743 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3744 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3746 return (current_frame_info
.mask
[reg_type
] & mask_bit
) != 0;
3752 /* Wrapper around emit_insn that sets RTX_FRAME_RELATED_P on the insn. */
3755 emit_frame_insn (rtx x
)
3758 RTX_FRAME_RELATED_P (x
) = 1;
3762 /* Allocate ALLOC bytes on the stack and save the registers LOW_REGNO to
3763 HIGH_REGNO at OFFSET from the stack pointer. */
3766 visium_save_regs (int alloc
, int offset
, int low_regno
, int high_regno
)
3768 /* If this is an interrupt handler function, then mark the register
3769 stores as volatile. This will prevent the instruction scheduler
3770 from scrambling the order of register saves. */
3771 const int volatile_p
= current_frame_info
.interrupt
;
3774 /* Allocate the stack space. */
3775 emit_frame_insn (gen_addsi3_flags (stack_pointer_rtx
, stack_pointer_rtx
,
3778 for (regno
= low_regno
; regno
<= high_regno
; regno
++)
3780 enum reg_type reg_type
= GET_REG_TYPE (regno
);
3781 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
3784 if (current_frame_info
.mask
[reg_type
] & mask_bit
)
3786 offset
-= reg_type_size
[reg_type
];
3792 = gen_frame_mem (SImode
,
3793 plus_constant (Pmode
,
3794 stack_pointer_rtx
, offset
));
3795 MEM_VOLATILE_P (mem
) = volatile_p
;
3796 emit_frame_insn (gen_movsi (mem
, gen_rtx_REG (SImode
, regno
)));
3802 rtx tmp
= gen_rtx_REG (DImode
, PROLOGUE_TMP_REGNUM
);
3804 = gen_frame_mem (DImode
,
3805 plus_constant (Pmode
,
3806 stack_pointer_rtx
, offset
));
3807 rtx reg
= gen_rtx_REG (DImode
, regno
);
3808 MEM_VOLATILE_P (mem
) = volatile_p
;
3809 emit_insn (gen_movdi (tmp
, reg
));
3810 /* Do not generate CFI if in interrupt handler. */
3812 emit_insn (gen_movdi (mem
, tmp
));
3815 insn
= emit_frame_insn (gen_movdi (mem
, tmp
));
3816 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3817 gen_rtx_SET (mem
, reg
));
3824 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
);
3826 = gen_frame_mem (SImode
,
3827 plus_constant (Pmode
,
3828 stack_pointer_rtx
, offset
));
3829 rtx reg
= gen_rtx_REG (SImode
, regno
);
3830 MEM_VOLATILE_P (mem
) = volatile_p
;
3831 emit_insn (gen_movsi (tmp
, reg
));
3832 insn
= emit_frame_insn (gen_movsi (mem
, tmp
));
3833 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3834 gen_rtx_SET (mem
, reg
));
3840 rtx tmp
= gen_rtx_REG (SFmode
, PROLOGUE_TMP_REGNUM
);
3842 = gen_frame_mem (SFmode
,
3843 plus_constant (Pmode
,
3844 stack_pointer_rtx
, offset
));
3845 rtx reg
= gen_rtx_REG (SFmode
, regno
);
3846 MEM_VOLATILE_P (mem
) = volatile_p
;
3847 emit_insn (gen_movsf (tmp
, reg
));
3848 insn
= emit_frame_insn (gen_movsf (mem
, tmp
));
3849 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3850 gen_rtx_SET (mem
, reg
));
3861 /* This function generates the code for function entry. */
3864 visium_expand_prologue (void)
3866 const int frame_size
= visium_compute_frame_size (get_frame_size ());
3867 const int save_area_size
= current_frame_info
.save_area_size
;
3868 const int reg_size1
= current_frame_info
.reg_size1
;
3869 const int max_reg1
= current_frame_info
.max_reg1
;
3870 const int reg_size2
= current_frame_info
.reg_size2
;
3871 const int var_size
= current_frame_info
.var_size
;
3872 const int save_fp
= current_frame_info
.save_fp
;
3873 const int save_lr
= current_frame_info
.save_lr
;
3874 const int lr_slot
= current_frame_info
.lr_slot
;
3875 const int local_frame_offset
3876 = (save_fp
+ save_lr
+ lr_slot
) * UNITS_PER_WORD
;
3877 const int combine
= current_frame_info
.combine
;
3882 /* Save the frame size for future references. */
3883 visium_frame_size
= frame_size
;
3885 if (flag_stack_usage_info
)
3886 current_function_static_stack_size
= frame_size
;
3888 /* If the registers have to be stacked in 2 blocks, stack the first one. */
3891 visium_save_regs (reg_size1
+ save_area_size
, reg_size1
, 0, max_reg1
);
3892 reg_size
= reg_size2
;
3893 first_reg
= max_reg1
+ 1;
3894 fsize
= local_frame_offset
+ var_size
+ reg_size2
;
3898 reg_size
= reg_size1
;
3900 fsize
= local_frame_offset
+ var_size
+ reg_size1
+ save_area_size
;
3903 /* If we can't combine register stacking with variable allocation, partially
3904 allocate and stack the (remaining) registers now. */
3905 if (reg_size
&& !combine
)
3906 visium_save_regs (fsize
- local_frame_offset
- var_size
, reg_size
,
3907 first_reg
, FIRST_PSEUDO_REGISTER
- 1);
3909 /* If we can combine register stacking with variable allocation, fully
3910 allocate and stack the (remaining) registers now. */
3911 if (reg_size
&& combine
)
3912 visium_save_regs (fsize
, local_frame_offset
+ var_size
+ reg_size
,
3913 first_reg
, FIRST_PSEUDO_REGISTER
- 1);
3915 /* Otherwise space may still need to be allocated for the variables. */
3918 const int alloc_size
= reg_size
? local_frame_offset
+ var_size
: fsize
;
3920 if (alloc_size
> 65535)
3922 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
), insn
;
3923 emit_insn (gen_movsi (tmp
, GEN_INT (alloc_size
)));
3924 insn
= emit_frame_insn (gen_subsi3_flags (stack_pointer_rtx
,
3927 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
3928 gen_rtx_SET (stack_pointer_rtx
,
3929 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
3930 GEN_INT (-alloc_size
))));
3933 emit_frame_insn (gen_addsi3_flags (stack_pointer_rtx
,
3935 GEN_INT (-alloc_size
)));
3939 emit_frame_insn (gen_movsi (gen_frame_mem (SImode
, stack_pointer_rtx
),
3940 hard_frame_pointer_rtx
));
3942 if (frame_pointer_needed
)
3943 emit_frame_insn (gen_stack_save ());
3949 /* Normally the frame pointer and link register get saved via
3954 Indexing off sp rather than fp to store the link register
3955 avoids presenting the instruction scheduler with an initial
3956 pipeline hazard. If however the frame is needed for eg.
3957 __builtin_return_address which needs to retrieve the saved
3958 value of the link register from the stack at fp + 4 then
3959 indexing from sp can confuse the dataflow, causing the link
3960 register to be retrieved before it has been saved. */
3961 if (cfun
->machine
->frame_needed
)
3962 base_rtx
= hard_frame_pointer_rtx
;
3964 base_rtx
= stack_pointer_rtx
;
3966 mem
= gen_frame_mem (SImode
,
3967 plus_constant (Pmode
,
3968 base_rtx
, save_fp
* UNITS_PER_WORD
));
3969 emit_frame_insn (gen_movsi (mem
, gen_rtx_REG (SImode
, LINK_REGNUM
)));
3973 static GTY(()) rtx cfa_restores
;
3975 /* Queue a REG_CFA_RESTORE note until next stack manipulation insn. */
3978 visium_add_cfa_restore_note (rtx reg
)
3980 cfa_restores
= alloc_reg_note (REG_CFA_RESTORE
, reg
, cfa_restores
);
3983 /* Add queued REG_CFA_RESTORE notes to INSN, if any. */
3986 visium_add_queued_cfa_restore_notes (rtx insn
)
3991 for (last
= cfa_restores
; XEXP (last
, 1); last
= XEXP (last
, 1))
3993 XEXP (last
, 1) = REG_NOTES (insn
);
3994 REG_NOTES (insn
) = cfa_restores
;
3995 cfa_restores
= NULL_RTX
;
3998 /* Restore the registers LOW_REGNO to HIGH_REGNO from the save area at OFFSET
3999 from the stack pointer and pop DEALLOC bytes off the stack. */
4002 visium_restore_regs (int dealloc
, int offset
, int high_regno
, int low_regno
)
4004 /* If this is an interrupt handler function, then mark the register
4005 restores as volatile. This will prevent the instruction scheduler
4006 from scrambling the order of register restores. */
4007 const int volatile_p
= current_frame_info
.interrupt
;
4008 int r30_offset
= -1;
4011 for (regno
= high_regno
; regno
>= low_regno
; --regno
)
4013 enum reg_type reg_type
= GET_REG_TYPE (regno
);
4014 int mask_bit
= 1 << (regno
- first_regno
[reg_type
]);
4016 if (current_frame_info
.mask
[reg_type
] & mask_bit
)
4021 /* Postpone restoring the interrupted context registers
4022 until last, since they need to be preceded by a dsi. */
4025 else if (regno
== 30)
4026 r30_offset
= offset
;
4030 = gen_frame_mem (SImode
,
4031 plus_constant (Pmode
,
4034 rtx reg
= gen_rtx_REG (SImode
, regno
);
4035 MEM_VOLATILE_P (mem
) = volatile_p
;
4036 emit_insn (gen_movsi (reg
, mem
));
4037 visium_add_cfa_restore_note (reg
);
4043 rtx tmp
= gen_rtx_REG (DImode
, PROLOGUE_TMP_REGNUM
);
4045 = gen_frame_mem (DImode
,
4046 plus_constant (Pmode
,
4047 stack_pointer_rtx
, offset
));
4048 rtx reg
= gen_rtx_REG (DImode
, regno
);
4049 MEM_VOLATILE_P (mem
) = volatile_p
;
4050 emit_insn (gen_movdi (tmp
, mem
));
4051 emit_insn (gen_movdi (reg
, tmp
));
4052 /* Do not generate CFI if in interrupt handler. */
4054 visium_add_cfa_restore_note (reg
);
4060 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
);
4062 = gen_frame_mem (SImode
,
4063 plus_constant (Pmode
,
4064 stack_pointer_rtx
, offset
));
4065 rtx reg
= gen_rtx_REG (SImode
, regno
);
4066 MEM_VOLATILE_P (mem
) = volatile_p
;
4067 emit_insn (gen_movsi (tmp
, mem
));
4068 emit_insn (gen_movsi (reg
, tmp
));
4069 visium_add_cfa_restore_note (reg
);
4075 rtx tmp
= gen_rtx_REG (SFmode
, PROLOGUE_TMP_REGNUM
);
4077 = gen_frame_mem (SFmode
,
4078 plus_constant (Pmode
,
4079 stack_pointer_rtx
, offset
));
4080 rtx reg
= gen_rtx_REG (SFmode
, regno
);
4081 MEM_VOLATILE_P (mem
) = volatile_p
;
4082 emit_insn (gen_movsf (tmp
, mem
));
4083 emit_insn (gen_movsf (reg
, tmp
));
4084 visium_add_cfa_restore_note (reg
);
4092 offset
+= reg_type_size
[reg_type
];
4096 /* If the interrupted context needs to be restored, precede the
4097 restores of r29 and r30 by a dsi. */
4098 if (r30_offset
>= 0)
4100 emit_insn (gen_dsi ());
4101 emit_move_insn (gen_rtx_REG (SImode
, 30),
4102 gen_frame_mem (SImode
,
4103 plus_constant (Pmode
,
4106 emit_move_insn (gen_rtx_REG (SImode
, 29),
4107 gen_frame_mem (SImode
,
4108 plus_constant (Pmode
,
4113 /* Deallocate the stack space. */
4114 rtx insn
= emit_frame_insn (gen_stack_pop (GEN_INT (dealloc
)));
4115 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
4116 gen_rtx_SET (stack_pointer_rtx
,
4117 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
4118 GEN_INT (dealloc
))));
4119 visium_add_queued_cfa_restore_notes (insn
);
4122 /* This function generates the code for function exit. */
4125 visium_expand_epilogue (void)
4127 const int save_area_size
= current_frame_info
.save_area_size
;
4128 const int reg_size1
= current_frame_info
.reg_size1
;
4129 const int max_reg1
= current_frame_info
.max_reg1
;
4130 const int reg_size2
= current_frame_info
.reg_size2
;
4131 const int var_size
= current_frame_info
.var_size
;
4132 const int restore_fp
= current_frame_info
.save_fp
;
4133 const int restore_lr
= current_frame_info
.save_lr
;
4134 const int lr_slot
= current_frame_info
.lr_slot
;
4135 const int local_frame_offset
4136 = (restore_fp
+ restore_lr
+ lr_slot
) * UNITS_PER_WORD
;
4137 const int combine
= current_frame_info
.combine
;
4142 /* Do not bother restoring the stack pointer if it hasn't been changed in
4143 the function since it was saved _after_ the allocation of the frame. */
4144 if (!crtl
->sp_is_unchanging
)
4145 emit_insn (gen_stack_restore ());
4147 /* Restore the frame pointer if necessary. The usual code would be:
4152 but for the MCM this constitutes a stall/hazard so it is changed to:
4157 if the stack pointer has actually been restored. */
4162 if (TARGET_MCM
&& !crtl
->sp_is_unchanging
)
4163 src
= gen_frame_mem (SImode
, hard_frame_pointer_rtx
);
4165 src
= gen_frame_mem (SImode
, stack_pointer_rtx
);
4167 rtx insn
= emit_frame_insn (gen_movsi (hard_frame_pointer_rtx
, src
));
4168 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
4169 gen_rtx_SET (stack_pointer_rtx
,
4170 hard_frame_pointer_rtx
));
4171 visium_add_cfa_restore_note (hard_frame_pointer_rtx
);
4174 /* Restore the link register if necessary. */
4177 rtx mem
= gen_frame_mem (SImode
,
4178 plus_constant (Pmode
,
4180 restore_fp
* UNITS_PER_WORD
));
4181 rtx reg
= gen_rtx_REG (SImode
, LINK_REGNUM
);
4182 emit_insn (gen_movsi (reg
, mem
));
4183 visium_add_cfa_restore_note (reg
);
4186 /* If we have two blocks of registers, deal with the second one first. */
4189 reg_size
= reg_size2
;
4190 last_reg
= max_reg1
+ 1;
4191 fsize
= local_frame_offset
+ var_size
+ reg_size2
;
4195 reg_size
= reg_size1
;
4197 fsize
= local_frame_offset
+ var_size
+ reg_size1
+ save_area_size
;
4200 /* If the variable allocation could be combined with register stacking,
4201 restore the (remaining) registers and fully deallocate now. */
4202 if (reg_size
&& combine
)
4203 visium_restore_regs (fsize
, local_frame_offset
+ var_size
,
4204 FIRST_PSEUDO_REGISTER
- 1, last_reg
);
4206 /* Otherwise deallocate the variables first. */
4209 const int pop_size
= reg_size
? local_frame_offset
+ var_size
: fsize
;
4212 if (pop_size
> 65535)
4214 rtx tmp
= gen_rtx_REG (SImode
, PROLOGUE_TMP_REGNUM
);
4215 emit_move_insn (tmp
, GEN_INT (pop_size
));
4216 insn
= emit_frame_insn (gen_stack_pop (tmp
));
4219 insn
= emit_frame_insn (gen_stack_pop (GEN_INT (pop_size
)));
4220 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
4221 gen_rtx_SET (stack_pointer_rtx
,
4222 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
4223 GEN_INT (pop_size
))));
4224 visium_add_queued_cfa_restore_notes (insn
);
4227 /* If the variable allocation couldn't be combined with register stacking,
4228 restore the (remaining) registers now and partially deallocate. */
4229 if (reg_size
&& !combine
)
4230 visium_restore_regs (fsize
- local_frame_offset
- var_size
, 0,
4231 FIRST_PSEUDO_REGISTER
- 1, last_reg
);
4233 /* If the first block of registers has yet to be restored, do it now. */
4235 visium_restore_regs (reg_size1
+ save_area_size
, 0, max_reg1
, 0);
4237 /* If this is an exception return, make the necessary stack adjustment. */
4238 if (crtl
->calls_eh_return
)
4239 emit_insn (gen_stack_pop (EH_RETURN_STACKADJ_RTX
));
4242 /* Return true if it is appropriate to emit `return' instructions in the
4243 body of a function. */
4246 visium_can_use_return_insn_p (void)
4248 return reload_completed
4249 && visium_frame_size
== 0
4250 && !visium_interrupt_function_p ();
4253 /* Return the register class required for an intermediate register used to
4254 copy a register of RCLASS from/to X. If no such intermediate register is
4255 required, return NO_REGS. If more than one such intermediate register is
4256 required, describe the one that is closest in the copy chain to the reload
4260 visium_secondary_reload (bool in_p ATTRIBUTE_UNUSED
, rtx x
,
4262 machine_mode mode ATTRIBUTE_UNUSED
,
4263 secondary_reload_info
*sri ATTRIBUTE_UNUSED
)
4265 int regno
= true_regnum (x
);
4267 /* For MDB, MDC and FP_REGS, a general register is needed for a move to
4269 if (regno
== -1 && (rclass
== MDB
|| rclass
== MDC
|| rclass
== FP_REGS
))
4270 return GENERAL_REGS
;
4272 /* Moves between MDB, MDC and FP_REGS also require a general register. */
4273 else if (((regno
== R_MDB
|| regno
== R_MDC
) && rclass
== FP_REGS
)
4274 || (FP_REGISTER_P (regno
) && (rclass
== MDB
|| rclass
== MDC
)))
4275 return GENERAL_REGS
;
4277 /* Finally an (unlikely ?) move between MDB and MDC needs a general reg. */
4278 else if ((regno
== R_MDB
&& rclass
== MDC
)
4279 || (rclass
== MDB
&& regno
== R_MDC
))
4280 return GENERAL_REGS
;
4285 /* Return true if pseudos that have been assigned to registers of RCLASS
4286 would likely be spilled because registers of RCLASS are needed for
4290 visium_class_likely_spilled_p (reg_class_t rclass ATTRIBUTE_UNUSED
)
4292 /* Return false for classes R1, R2 and R3, which are intended to be used
4293 only in the source code in conjunction with block move instructions. */
4297 /* Return the register number if OP is a REG or a SUBREG of a REG, and
4298 INVALID_REGNUM in all the other cases. */
4301 reg_or_subreg_regno (rtx op
)
4305 if (GET_CODE (op
) == REG
)
4307 else if (GET_CODE (op
) == SUBREG
&& GET_CODE (SUBREG_REG (op
)) == REG
)
4309 if (REGNO (SUBREG_REG (op
)) < FIRST_PSEUDO_REGISTER
)
4310 regno
= subreg_regno (op
);
4312 regno
= REGNO (SUBREG_REG (op
));
4315 regno
= INVALID_REGNUM
;
4320 /* Implement TARGET_CAN_CHANGE_MODE_CLASS.
4322 It's not obvious from the documentation of the hook that MDB cannot
4323 change mode. However difficulties arise from expressions of the form
4325 (subreg:SI (reg:DI R_MDB) 0)
4327 There is no way to convert that reference to a single machine
4328 register and, without the following definition, reload will quietly
4334 visium_can_change_mode_class (machine_mode from
, machine_mode to
,
4337 return (rclass
!= MDB
|| GET_MODE_SIZE (from
) == GET_MODE_SIZE (to
));
4340 #include "gt-visium.h"