Home | History | Annotate | Line # | Download | only in visium
      1  1.1  mrg /* Output routines for Visium.
      2  1.1  mrg    Copyright (C) 2002-2022 Free Software Foundation, Inc.
      3  1.1  mrg    Contributed by C.Nettleton, J.P.Parkes and P.Garbett.
      4  1.1  mrg 
      5  1.1  mrg    This file is part of GCC.
      6  1.1  mrg 
      7  1.1  mrg    GCC is free software; you can redistribute it and/or modify it
      8  1.1  mrg    under the terms of the GNU General Public License as published
      9  1.1  mrg    by the Free Software Foundation; either version 3, or (at your
     10  1.1  mrg    option) any later version.
     11  1.1  mrg 
     12  1.1  mrg    GCC is distributed in the hope that it will be useful, but WITHOUT
     13  1.1  mrg    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     14  1.1  mrg    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     15  1.1  mrg    License for more details.
     16  1.1  mrg 
     17  1.1  mrg    You should have received a copy of the GNU General Public License
     18  1.1  mrg    along with GCC; see the file COPYING3.  If not see
     19  1.1  mrg    <http://www.gnu.org/licenses/>.  */
     20  1.1  mrg 
     21  1.1  mrg #define IN_TARGET_CODE 1
     22  1.1  mrg 
     23  1.1  mrg #include "config.h"
     24  1.1  mrg #include "system.h"
     25  1.1  mrg #include "coretypes.h"
     26  1.1  mrg #include "backend.h"
     27  1.1  mrg #include "target.h"
     28  1.1  mrg #include "rtl.h"
     29  1.1  mrg #include "tree.h"
     30  1.1  mrg #include "gimple-expr.h"
     31  1.1  mrg #include "df.h"
     32  1.1  mrg #include "memmodel.h"
     33  1.1  mrg #include "tm_p.h"
     34  1.1  mrg #include "stringpool.h"
     35  1.1  mrg #include "attribs.h"
     36  1.1  mrg #include "expmed.h"
     37  1.1  mrg #include "optabs.h"
     38  1.1  mrg #include "regs.h"
     39  1.1  mrg #include "emit-rtl.h"
     40  1.1  mrg #include "recog.h"
     41  1.1  mrg #include "diagnostic-core.h"
     42  1.1  mrg #include "alias.h"
     43  1.1  mrg #include "flags.h"
     44  1.1  mrg #include "fold-const.h"
     45  1.1  mrg #include "stor-layout.h"
     46  1.1  mrg #include "calls.h"
     47  1.1  mrg #include "varasm.h"
     48  1.1  mrg #include "output.h"
     49  1.1  mrg #include "insn-attr.h"
     50  1.1  mrg #include "explow.h"
     51  1.1  mrg #include "expr.h"
     52  1.1  mrg #include "gimplify.h"
     53  1.1  mrg #include "langhooks.h"
     54  1.1  mrg #include "reload.h"
     55  1.1  mrg #include "tm-constrs.h"
     56  1.1  mrg #include "tree-pass.h"
     57  1.1  mrg #include "context.h"
     58  1.1  mrg #include "builtins.h"
     59  1.1  mrg #include "opts.h"
     60  1.1  mrg 
     61  1.1  mrg /* This file should be included last.  */
     62  1.1  mrg #include "target-def.h"
     63  1.1  mrg 
     64  1.1  mrg /* Enumeration of indexes into machine_libfunc_table.  */
     65  1.1  mrg enum machine_libfunc_index
     66  1.1  mrg {
     67  1.1  mrg   MLTI_long_int_memcpy,
     68  1.1  mrg   MLTI_wrd_memcpy,
     69  1.1  mrg   MLTI_byt_memcpy,
     70  1.1  mrg 
     71  1.1  mrg   MLTI_long_int_memset,
     72  1.1  mrg   MLTI_wrd_memset,
     73  1.1  mrg   MLTI_byt_memset,
     74  1.1  mrg 
     75  1.1  mrg   MLTI_set_trampoline_parity,
     76  1.1  mrg 
     77  1.1  mrg   MLTI_MAX
     78  1.1  mrg };
     79  1.1  mrg 
     80  1.1  mrg struct GTY(()) machine_libfuncs
     81  1.1  mrg {
     82  1.1  mrg   rtx table[MLTI_MAX];
     83  1.1  mrg };
     84  1.1  mrg 
     85  1.1  mrg /* The table of Visium-specific libfuncs.  */
     86  1.1  mrg static GTY(()) struct machine_libfuncs visium_libfuncs;
     87  1.1  mrg 
     88  1.1  mrg #define vlt visium_libfuncs.table
     89  1.1  mrg 
     90  1.1  mrg /* Accessor macros for visium_libfuncs.  */
     91  1.1  mrg #define long_int_memcpy_libfunc		(vlt[MLTI_long_int_memcpy])
     92  1.1  mrg #define wrd_memcpy_libfunc		(vlt[MLTI_wrd_memcpy])
     93  1.1  mrg #define byt_memcpy_libfunc		(vlt[MLTI_byt_memcpy])
     94  1.1  mrg #define long_int_memset_libfunc		(vlt[MLTI_long_int_memset])
     95  1.1  mrg #define wrd_memset_libfunc		(vlt[MLTI_wrd_memset])
     96  1.1  mrg #define byt_memset_libfunc		(vlt[MLTI_byt_memset])
     97  1.1  mrg #define set_trampoline_parity_libfunc	(vlt[MLTI_set_trampoline_parity])
     98  1.1  mrg 
     99  1.1  mrg /* Machine specific function data. */
    100  1.1  mrg struct GTY (()) machine_function
    101  1.1  mrg {
    102  1.1  mrg   /* Size of the frame of the function.  */
    103  1.1  mrg   int frame_size;
    104  1.1  mrg 
    105  1.1  mrg   /* Size of the reg parm save area, non-zero only for functions with variable
    106  1.1  mrg      argument list.  We cannot use the crtl->args.pretend_args_size machinery
    107  1.1  mrg      for this purpose because this size is added to virtual_incoming_args_rtx
    108  1.1  mrg      to give the location of the first parameter passed by the caller on the
    109  1.1  mrg      stack and virtual_incoming_args_rtx is also the location of the first
    110  1.1  mrg      parameter on the stack.  So crtl->args.pretend_args_size can be non-zero
    111  1.1  mrg      only if the first non-register named parameter is not passed entirely on
    112  1.1  mrg      the stack and this runs afoul of the need to have a reg parm save area
    113  1.1  mrg      even with a variable argument list starting on the stack because of the
    114  1.1  mrg      separate handling of general and floating-point registers.  */
    115  1.1  mrg   int reg_parm_save_area_size;
    116  1.1  mrg 
    117  1.1  mrg   /* True if we have created an rtx which relies on the frame pointer.  */
    118  1.1  mrg   bool frame_needed;
    119  1.1  mrg 
    120  1.1  mrg   /* True if we have exposed the flags register.  From this moment on, we
    121  1.1  mrg      cannot generate simple operations for integer registers.  We could
    122  1.1  mrg      use reload_completed for this purpose, but this would cripple the
    123  1.1  mrg      postreload CSE and GCSE passes which run before postreload split.  */
    124  1.1  mrg   bool flags_exposed;
    125  1.1  mrg };
    126  1.1  mrg 
    127  1.1  mrg #define visium_frame_size		cfun->machine->frame_size
    128  1.1  mrg #define visium_reg_parm_save_area_size 	cfun->machine->reg_parm_save_area_size
    129  1.1  mrg #define visium_frame_needed		cfun->machine->frame_needed
    130  1.1  mrg #define visium_flags_exposed		cfun->machine->flags_exposed
    131  1.1  mrg 
    132  1.1  mrg /* 1 if the next opcode is to be specially indented.  */
    133  1.1  mrg int visium_indent_opcode = 0;
    134  1.1  mrg 
    135  1.1  mrg /* Register number used for long branches when LR isn't available.  It
    136  1.1  mrg    must be a call-used register since it isn't saved on function entry.
    137  1.1  mrg    We do not care whether the branch is predicted or not on the GR6,
    138  1.1  mrg    given how unlikely it is to have a long branch in a leaf function.  */
    139  1.1  mrg static unsigned int long_branch_regnum = 31;
    140  1.1  mrg 
    141  1.1  mrg static tree visium_handle_interrupt_attr (tree *, tree, tree, int, bool *);
    142  1.1  mrg static inline bool current_function_saves_fp (void);
    143  1.1  mrg static inline bool current_function_saves_lr (void);
    144  1.1  mrg static inline bool current_function_has_lr_slot (void);
    145  1.1  mrg 
    146  1.1  mrg /* Supported attributes:
    147  1.1  mrg    interrupt -- specifies this function is an interrupt handler.   */
    148  1.1  mrg static const struct attribute_spec visium_attribute_table[] =
    149  1.1  mrg {
    150  1.1  mrg   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
    151  1.1  mrg        affects_type_identity, handler, exclude } */
    152  1.1  mrg   { "interrupt", 0, 0, true, false, false, false, visium_handle_interrupt_attr,
    153  1.1  mrg     NULL},
    154  1.1  mrg   { NULL, 0, 0, false, false, false, false, NULL, NULL },
    155  1.1  mrg };
    156  1.1  mrg 
    157  1.1  mrg static struct machine_function *visium_init_machine_status (void);
    158  1.1  mrg 
    159  1.1  mrg /* Target hooks and TARGET_INITIALIZER  */
    160  1.1  mrg 
    161  1.1  mrg static bool visium_pass_by_reference (cumulative_args_t,
    162  1.1  mrg 				      const function_arg_info &);
    163  1.1  mrg 
    164  1.1  mrg static rtx visium_function_arg (cumulative_args_t, const function_arg_info &);
    165  1.1  mrg 
    166  1.1  mrg static void visium_function_arg_advance (cumulative_args_t,
    167  1.1  mrg 					 const function_arg_info &);
    168  1.1  mrg 
    169  1.1  mrg static bool visium_return_in_memory (const_tree, const_tree fntype);
    170  1.1  mrg 
    171  1.1  mrg static rtx visium_function_value (const_tree, const_tree fn_decl_or_type,
    172  1.1  mrg 				  bool);
    173  1.1  mrg 
    174  1.1  mrg static rtx visium_libcall_value (machine_mode, const_rtx);
    175  1.1  mrg 
    176  1.1  mrg static void visium_setup_incoming_varargs (cumulative_args_t,
    177  1.1  mrg 					   const function_arg_info &,
    178  1.1  mrg 					   int *, int);
    179  1.1  mrg 
    180  1.1  mrg static void visium_va_start (tree valist, rtx nextarg);
    181  1.1  mrg 
    182  1.1  mrg static tree visium_gimplify_va_arg (tree, tree, gimple_seq *, gimple_seq *);
    183  1.1  mrg 
    184  1.1  mrg static bool visium_function_ok_for_sibcall (tree, tree);
    185  1.1  mrg 
    186  1.1  mrg static bool visium_frame_pointer_required (void);
    187  1.1  mrg 
    188  1.1  mrg static tree visium_build_builtin_va_list (void);
    189  1.1  mrg 
    190  1.1  mrg static rtx_insn *visium_md_asm_adjust (vec<rtx> &, vec<rtx> &,
    191  1.1  mrg 				       vec<machine_mode> &,
    192  1.1  mrg 				       vec<const char *> &, vec<rtx> &,
    193  1.1  mrg 				       HARD_REG_SET &, location_t);
    194  1.1  mrg 
    195  1.1  mrg static bool visium_legitimate_constant_p (machine_mode, rtx);
    196  1.1  mrg 
    197  1.1  mrg static bool visium_legitimate_address_p (machine_mode, rtx, bool);
    198  1.1  mrg 
    199  1.1  mrg static bool visium_print_operand_punct_valid_p (unsigned char);
    200  1.1  mrg static void visium_print_operand (FILE *, rtx, int);
    201  1.1  mrg static void visium_print_operand_address (FILE *, machine_mode, rtx);
    202  1.1  mrg 
    203  1.1  mrg static void visium_conditional_register_usage (void);
    204  1.1  mrg 
    205  1.1  mrg static rtx visium_legitimize_address (rtx, rtx, machine_mode);
    206  1.1  mrg 
    207  1.1  mrg static reg_class_t visium_secondary_reload (bool, rtx, reg_class_t,
    208  1.1  mrg 					    machine_mode,
    209  1.1  mrg 					    secondary_reload_info *);
    210  1.1  mrg 
    211  1.1  mrg static bool visium_class_likely_spilled_p (reg_class_t);
    212  1.1  mrg 
    213  1.1  mrg static void visium_trampoline_init (rtx, tree, rtx);
    214  1.1  mrg 
    215  1.1  mrg static int visium_issue_rate (void);
    216  1.1  mrg 
    217  1.1  mrg static int visium_adjust_priority (rtx_insn *, int);
    218  1.1  mrg 
    219  1.1  mrg static int visium_adjust_cost (rtx_insn *, int, rtx_insn *, int, unsigned int);
    220  1.1  mrg 
    221  1.1  mrg static int visium_register_move_cost (machine_mode, reg_class_t,
    222  1.1  mrg 				      reg_class_t);
    223  1.1  mrg 
    224  1.1  mrg static int visium_memory_move_cost (machine_mode, reg_class_t, bool);
    225  1.1  mrg 
    226  1.1  mrg static bool visium_rtx_costs (rtx, machine_mode, int, int, int *, bool);
    227  1.1  mrg 
    228  1.1  mrg static void visium_option_override (void);
    229  1.1  mrg 
    230  1.1  mrg static void visium_init_libfuncs (void);
    231  1.1  mrg 
    232  1.1  mrg static unsigned int visium_reorg (void);
    233  1.1  mrg 
    234  1.1  mrg static unsigned int visium_hard_regno_nregs (unsigned int, machine_mode);
    235  1.1  mrg 
    236  1.1  mrg static bool visium_hard_regno_mode_ok (unsigned int, machine_mode);
    237  1.1  mrg 
    238  1.1  mrg static bool visium_modes_tieable_p (machine_mode, machine_mode);
    239  1.1  mrg 
    240  1.1  mrg static bool visium_can_change_mode_class (machine_mode, machine_mode,
    241  1.1  mrg 					  reg_class_t);
    242  1.1  mrg 
    243  1.1  mrg static HOST_WIDE_INT visium_constant_alignment (const_tree, HOST_WIDE_INT);
    244  1.1  mrg 
    245  1.1  mrg /* Setup the global target hooks structure.  */
    246  1.1  mrg 
    247  1.1  mrg #undef  TARGET_MAX_ANCHOR_OFFSET
    248  1.1  mrg #define TARGET_MAX_ANCHOR_OFFSET 31
    249  1.1  mrg 
    250  1.1  mrg #undef  TARGET_PASS_BY_REFERENCE
    251  1.1  mrg #define TARGET_PASS_BY_REFERENCE visium_pass_by_reference
    252  1.1  mrg 
    253  1.1  mrg #undef  TARGET_FUNCTION_ARG
    254  1.1  mrg #define TARGET_FUNCTION_ARG visium_function_arg
    255  1.1  mrg 
    256  1.1  mrg #undef  TARGET_FUNCTION_ARG_ADVANCE
    257  1.1  mrg #define TARGET_FUNCTION_ARG_ADVANCE visium_function_arg_advance
    258  1.1  mrg 
    259  1.1  mrg #undef  TARGET_RETURN_IN_MEMORY
    260  1.1  mrg #define TARGET_RETURN_IN_MEMORY visium_return_in_memory
    261  1.1  mrg 
    262  1.1  mrg #undef  TARGET_FUNCTION_VALUE
    263  1.1  mrg #define TARGET_FUNCTION_VALUE visium_function_value
    264  1.1  mrg 
    265  1.1  mrg #undef  TARGET_LIBCALL_VALUE
    266  1.1  mrg #define TARGET_LIBCALL_VALUE visium_libcall_value
    267  1.1  mrg 
    268  1.1  mrg #undef  TARGET_SETUP_INCOMING_VARARGS
    269  1.1  mrg #define TARGET_SETUP_INCOMING_VARARGS visium_setup_incoming_varargs
    270  1.1  mrg 
    271  1.1  mrg #undef  TARGET_EXPAND_BUILTIN_VA_START
    272  1.1  mrg #define TARGET_EXPAND_BUILTIN_VA_START visium_va_start
    273  1.1  mrg 
    274  1.1  mrg #undef  TARGET_BUILD_BUILTIN_VA_LIST
    275  1.1  mrg #define TARGET_BUILD_BUILTIN_VA_LIST visium_build_builtin_va_list
    276  1.1  mrg 
    277  1.1  mrg #undef  TARGET_GIMPLIFY_VA_ARG_EXPR
    278  1.1  mrg #define TARGET_GIMPLIFY_VA_ARG_EXPR visium_gimplify_va_arg
    279  1.1  mrg 
    280  1.1  mrg #undef  TARGET_LEGITIMATE_CONSTANT_P
    281  1.1  mrg #define TARGET_LEGITIMATE_CONSTANT_P visium_legitimate_constant_p
    282  1.1  mrg 
    283  1.1  mrg #undef  TARGET_LRA_P
    284  1.1  mrg #define TARGET_LRA_P hook_bool_void_false
    285  1.1  mrg 
    286  1.1  mrg #undef  TARGET_LEGITIMATE_ADDRESS_P
    287  1.1  mrg #define TARGET_LEGITIMATE_ADDRESS_P visium_legitimate_address_p
    288  1.1  mrg 
    289  1.1  mrg #undef  TARGET_PRINT_OPERAND_PUNCT_VALID_P
    290  1.1  mrg #define TARGET_PRINT_OPERAND_PUNCT_VALID_P visium_print_operand_punct_valid_p
    291  1.1  mrg 
    292  1.1  mrg #undef  TARGET_PRINT_OPERAND
    293  1.1  mrg #define TARGET_PRINT_OPERAND visium_print_operand
    294  1.1  mrg 
    295  1.1  mrg #undef  TARGET_PRINT_OPERAND_ADDRESS
    296  1.1  mrg #define TARGET_PRINT_OPERAND_ADDRESS visium_print_operand_address
    297  1.1  mrg 
    298  1.1  mrg #undef  TARGET_ATTRIBUTE_TABLE
    299  1.1  mrg #define TARGET_ATTRIBUTE_TABLE visium_attribute_table
    300  1.1  mrg 
    301  1.1  mrg #undef  TARGET_ADDRESS_COST
    302  1.1  mrg #define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
    303  1.1  mrg 
    304  1.1  mrg #undef  TARGET_STRICT_ARGUMENT_NAMING
    305  1.1  mrg #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
    306  1.1  mrg 
    307  1.1  mrg #undef  TARGET_SCHED_ISSUE_RATE
    308  1.1  mrg #define TARGET_SCHED_ISSUE_RATE visium_issue_rate
    309  1.1  mrg 
    310  1.1  mrg #undef  TARGET_SCHED_ADJUST_PRIORITY
    311  1.1  mrg #define TARGET_SCHED_ADJUST_PRIORITY visium_adjust_priority
    312  1.1  mrg 
    313  1.1  mrg #undef  TARGET_SCHED_ADJUST_COST
    314  1.1  mrg #define TARGET_SCHED_ADJUST_COST visium_adjust_cost
    315  1.1  mrg 
    316  1.1  mrg #undef  TARGET_MEMORY_MOVE_COST
    317  1.1  mrg #define TARGET_MEMORY_MOVE_COST visium_memory_move_cost
    318  1.1  mrg 
    319  1.1  mrg #undef  TARGET_REGISTER_MOVE_COST
    320  1.1  mrg #define TARGET_REGISTER_MOVE_COST visium_register_move_cost
    321  1.1  mrg 
    322  1.1  mrg #undef  TARGET_RTX_COSTS
    323  1.1  mrg #define TARGET_RTX_COSTS visium_rtx_costs
    324  1.1  mrg 
    325  1.1  mrg #undef  TARGET_FUNCTION_OK_FOR_SIBCALL
    326  1.1  mrg #define TARGET_FUNCTION_OK_FOR_SIBCALL visium_function_ok_for_sibcall
    327  1.1  mrg 
    328  1.1  mrg #undef  TARGET_FRAME_POINTER_REQUIRED
    329  1.1  mrg #define TARGET_FRAME_POINTER_REQUIRED visium_frame_pointer_required
    330  1.1  mrg 
    331  1.1  mrg #undef  TARGET_SECONDARY_RELOAD
    332  1.1  mrg #define TARGET_SECONDARY_RELOAD visium_secondary_reload
    333  1.1  mrg 
    334  1.1  mrg #undef  TARGET_CLASS_LIKELY_SPILLED_P
    335  1.1  mrg #define TARGET_CLASS_LIKELY_SPILLED_P visium_class_likely_spilled_p
    336  1.1  mrg 
    337  1.1  mrg #undef  TARGET_LEGITIMIZE_ADDRESS
    338  1.1  mrg #define TARGET_LEGITIMIZE_ADDRESS visium_legitimize_address
    339  1.1  mrg 
    340  1.1  mrg #undef  TARGET_OPTION_OVERRIDE
    341  1.1  mrg #define TARGET_OPTION_OVERRIDE visium_option_override
    342  1.1  mrg 
    343  1.1  mrg #undef  TARGET_INIT_LIBFUNCS
    344  1.1  mrg #define TARGET_INIT_LIBFUNCS visium_init_libfuncs
    345  1.1  mrg 
    346  1.1  mrg #undef  TARGET_CONDITIONAL_REGISTER_USAGE
    347  1.1  mrg #define TARGET_CONDITIONAL_REGISTER_USAGE visium_conditional_register_usage
    348  1.1  mrg 
    349  1.1  mrg #undef  TARGET_TRAMPOLINE_INIT
    350  1.1  mrg #define TARGET_TRAMPOLINE_INIT visium_trampoline_init
    351  1.1  mrg 
    352  1.1  mrg #undef  TARGET_MD_ASM_ADJUST
    353  1.1  mrg #define TARGET_MD_ASM_ADJUST visium_md_asm_adjust
    354  1.1  mrg 
    355  1.1  mrg #undef  TARGET_FLAGS_REGNUM
    356  1.1  mrg #define TARGET_FLAGS_REGNUM FLAGS_REGNUM
    357  1.1  mrg 
    358  1.1  mrg #undef  TARGET_HARD_REGNO_NREGS
    359  1.1  mrg #define TARGET_HARD_REGNO_NREGS visium_hard_regno_nregs
    360  1.1  mrg 
    361  1.1  mrg #undef  TARGET_HARD_REGNO_MODE_OK
    362  1.1  mrg #define TARGET_HARD_REGNO_MODE_OK visium_hard_regno_mode_ok
    363  1.1  mrg 
    364  1.1  mrg #undef  TARGET_MODES_TIEABLE_P
    365  1.1  mrg #define TARGET_MODES_TIEABLE_P visium_modes_tieable_p
    366  1.1  mrg 
    367  1.1  mrg #undef  TARGET_CAN_CHANGE_MODE_CLASS
    368  1.1  mrg #define TARGET_CAN_CHANGE_MODE_CLASS visium_can_change_mode_class
    369  1.1  mrg 
    370  1.1  mrg #undef  TARGET_CONSTANT_ALIGNMENT
    371  1.1  mrg #define TARGET_CONSTANT_ALIGNMENT visium_constant_alignment
    372  1.1  mrg 
    373  1.1  mrg #undef  TARGET_HAVE_SPECULATION_SAFE_VALUE
    374  1.1  mrg #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
    375  1.1  mrg 
    376  1.1  mrg struct gcc_target targetm = TARGET_INITIALIZER;
    377  1.1  mrg 
    378  1.1  mrg namespace {
    379  1.1  mrg 
    380  1.1  mrg const pass_data pass_data_visium_reorg =
    381  1.1  mrg {
    382  1.1  mrg   RTL_PASS, /* type */
    383  1.1  mrg   "mach2", /* name */
    384  1.1  mrg   OPTGROUP_NONE, /* optinfo_flags */
    385  1.1  mrg   TV_MACH_DEP, /* tv_id */
    386  1.1  mrg   0, /* properties_required */
    387  1.1  mrg   0, /* properties_provided */
    388  1.1  mrg   0, /* properties_destroyed */
    389  1.1  mrg   0, /* todo_flags_start */
    390  1.1  mrg   0, /* todo_flags_finish */
    391  1.1  mrg };
    392  1.1  mrg 
    393  1.1  mrg class pass_visium_reorg : public rtl_opt_pass
    394  1.1  mrg {
    395  1.1  mrg public:
    396  1.1  mrg   pass_visium_reorg(gcc::context *ctxt)
    397  1.1  mrg     : rtl_opt_pass(pass_data_visium_reorg, ctxt)
    398  1.1  mrg   {}
    399  1.1  mrg 
    400  1.1  mrg   /* opt_pass methods: */
    401  1.1  mrg   virtual unsigned int execute (function *)
    402  1.1  mrg     {
    403  1.1  mrg       return visium_reorg ();
    404  1.1  mrg     }
    405  1.1  mrg 
    406  1.1  mrg }; // class pass_work_around_errata
    407  1.1  mrg 
    408  1.1  mrg } // anon namespace
    409  1.1  mrg 
    410  1.1  mrg rtl_opt_pass *
    411  1.1  mrg make_pass_visium_reorg (gcc::context *ctxt)
    412  1.1  mrg {
    413  1.1  mrg   return new pass_visium_reorg (ctxt);
    414  1.1  mrg }
    415  1.1  mrg 
    416  1.1  mrg /* Options override for Visium.  */
    417  1.1  mrg 
    418  1.1  mrg static void
    419  1.1  mrg visium_option_override (void)
    420  1.1  mrg {
    421  1.1  mrg   if (flag_pic == 1)
    422  1.1  mrg     warning (OPT_fpic, "%<-fpic%> is not supported");
    423  1.1  mrg   if (flag_pic == 2)
    424  1.1  mrg     warning (OPT_fPIC, "%<-fPIC%> is not supported");
    425  1.1  mrg 
    426  1.1  mrg   /* MCM is the default in the GR5/GR6 era.  */
    427  1.1  mrg   target_flags |= MASK_MCM;
    428  1.1  mrg 
    429  1.1  mrg   /* FPU is the default with MCM, but don't override an explicit option.  */
    430  1.1  mrg   if ((target_flags_explicit & MASK_FPU) == 0)
    431  1.1  mrg     target_flags |= MASK_FPU;
    432  1.1  mrg 
    433  1.1  mrg   /* The supervisor mode is the default.  */
    434  1.1  mrg   if ((target_flags_explicit & MASK_SV_MODE) == 0)
    435  1.1  mrg     target_flags |= MASK_SV_MODE;
    436  1.1  mrg 
    437  1.1  mrg   /* The GR6 has the Block Move Instructions and an IEEE-compliant FPU.  */
    438  1.1  mrg   if (visium_cpu_and_features == PROCESSOR_GR6)
    439  1.1  mrg     {
    440  1.1  mrg       target_flags |= MASK_BMI;
    441  1.1  mrg       if (target_flags & MASK_FPU)
    442  1.1  mrg 	target_flags |= MASK_FPU_IEEE;
    443  1.1  mrg     }
    444  1.1  mrg 
    445  1.1  mrg   /* Set -mtune from -mcpu if not specified.  */
    446  1.1  mrg   if (!OPTION_SET_P (visium_cpu))
    447  1.1  mrg     visium_cpu = visium_cpu_and_features;
    448  1.1  mrg 
    449  1.1  mrg   /* Align functions on 256-byte (32-quadword) for GR5 and 64-byte (8-quadword)
    450  1.1  mrg      boundaries for GR6 so they start a new burst mode window.  */
    451  1.1  mrg   if (flag_align_functions && !str_align_functions)
    452  1.1  mrg     {
    453  1.1  mrg       if (visium_cpu == PROCESSOR_GR6)
    454  1.1  mrg 	str_align_functions = "64";
    455  1.1  mrg       else
    456  1.1  mrg 	str_align_functions = "256";
    457  1.1  mrg 
    458  1.1  mrg       /* Allow the size of compilation units to double because of inlining.
    459  1.1  mrg 	 In practice the global size of the object code is hardly affected
    460  1.1  mrg 	 because the additional instructions will take up the padding.  */
    461  1.1  mrg       SET_OPTION_IF_UNSET (&global_options, &global_options_set,
    462  1.1  mrg 			   param_inline_unit_growth, 100);
    463  1.1  mrg     }
    464  1.1  mrg 
    465  1.1  mrg   /* Likewise for loops.  */
    466  1.1  mrg   if (flag_align_loops && !str_align_loops)
    467  1.1  mrg     {
    468  1.1  mrg       if (visium_cpu == PROCESSOR_GR6)
    469  1.1  mrg 	str_align_loops = "64";
    470  1.1  mrg       else
    471  1.1  mrg 	{
    472  1.1  mrg 	  /* But not if they are too far away from a 256-byte boundary.  */
    473  1.1  mrg 	  str_align_loops = "256:32:8";
    474  1.1  mrg 	}
    475  1.1  mrg     }
    476  1.1  mrg 
    477  1.1  mrg   /* Align all jumps on quadword boundaries for the burst mode, and even
    478  1.1  mrg      on 8-quadword boundaries for GR6 so they start a new window.  */
    479  1.1  mrg   if (flag_align_jumps && !str_align_jumps)
    480  1.1  mrg     {
    481  1.1  mrg       if (visium_cpu == PROCESSOR_GR6)
    482  1.1  mrg 	str_align_jumps = "64";
    483  1.1  mrg       else
    484  1.1  mrg 	str_align_jumps = "8";
    485  1.1  mrg     }
    486  1.1  mrg }
    487  1.1  mrg 
    488  1.1  mrg /* Register the Visium-specific libfuncs with the middle-end.  */
    489  1.1  mrg 
    490  1.1  mrg static void
    491  1.1  mrg visium_init_libfuncs (void)
    492  1.1  mrg {
    493  1.1  mrg   if (!TARGET_BMI)
    494  1.1  mrg     long_int_memcpy_libfunc = init_one_libfunc ("__long_int_memcpy");
    495  1.1  mrg   wrd_memcpy_libfunc = init_one_libfunc ("__wrd_memcpy");
    496  1.1  mrg   byt_memcpy_libfunc = init_one_libfunc ("__byt_memcpy");
    497  1.1  mrg 
    498  1.1  mrg   long_int_memset_libfunc = init_one_libfunc ("__long_int_memset");
    499  1.1  mrg   wrd_memset_libfunc = init_one_libfunc ("__wrd_memset");
    500  1.1  mrg   byt_memset_libfunc = init_one_libfunc ("__byt_memset");
    501  1.1  mrg 
    502  1.1  mrg   set_trampoline_parity_libfunc = init_one_libfunc ("__set_trampoline_parity");
    503  1.1  mrg }
    504  1.1  mrg 
    505  1.1  mrg /* Return the number of instructions that can issue on the same cycle.  */
    506  1.1  mrg 
    507  1.1  mrg static int
    508  1.1  mrg visium_issue_rate (void)
    509  1.1  mrg {
    510  1.1  mrg   switch (visium_cpu)
    511  1.1  mrg     {
    512  1.1  mrg     case PROCESSOR_GR5:
    513  1.1  mrg       return 1;
    514  1.1  mrg 
    515  1.1  mrg     case PROCESSOR_GR6:
    516  1.1  mrg       return 2;
    517  1.1  mrg 
    518  1.1  mrg     default:
    519  1.1  mrg       gcc_unreachable ();
    520  1.1  mrg     }
    521  1.1  mrg }
    522  1.1  mrg 
    523  1.1  mrg /* Return the adjusted PRIORITY of INSN.  */
    524  1.1  mrg 
    525  1.1  mrg static int
    526  1.1  mrg visium_adjust_priority (rtx_insn *insn, int priority)
    527  1.1  mrg {
    528  1.1  mrg   /* On the GR5, we slightly increase the priority of writes in order to avoid
    529  1.1  mrg      scheduling a read on the next cycle.  This is necessary in addition to the
    530  1.1  mrg      associated insn reservation because there are no data dependencies.
    531  1.1  mrg      We also slightly increase the priority of reads from ROM in order to group
    532  1.1  mrg      them as much as possible.  These reads are a bit problematic because they
    533  1.1  mrg      conflict with the instruction fetches, i.e. the data and instruction buses
    534  1.1  mrg      tread on each other's toes when they are executed.  */
    535  1.1  mrg   if (visium_cpu == PROCESSOR_GR5
    536  1.1  mrg       && reload_completed
    537  1.1  mrg       && INSN_P (insn)
    538  1.1  mrg       && recog_memoized (insn) >= 0)
    539  1.1  mrg     {
    540  1.1  mrg       enum attr_type attr_type = get_attr_type (insn);
    541  1.1  mrg       if (attr_type == TYPE_REG_MEM
    542  1.1  mrg 	  || (attr_type == TYPE_MEM_REG
    543  1.1  mrg 	      && MEM_READONLY_P (SET_SRC (PATTERN (insn)))))
    544  1.1  mrg 	return priority + 1;
    545  1.1  mrg     }
    546  1.1  mrg 
    547  1.1  mrg   return priority;
    548  1.1  mrg }
    549  1.1  mrg 
    550  1.1  mrg /* Adjust the cost of a scheduling dependency.  Return the new cost of
    551  1.1  mrg    a dependency LINK of INSN on DEP_INSN.  COST is the current cost.  */
    552  1.1  mrg 
    553  1.1  mrg static int
    554  1.1  mrg visium_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost,
    555  1.1  mrg 		    unsigned int)
    556  1.1  mrg {
    557  1.1  mrg   enum attr_type attr_type;
    558  1.1  mrg 
    559  1.1  mrg   /* Don't adjust costs for true dependencies as they are described with
    560  1.1  mrg      bypasses.  But we make an exception for the first scheduling pass to
    561  1.1  mrg      help the subsequent postreload compare elimination pass.  */
    562  1.1  mrg   if (dep_type == REG_DEP_TRUE)
    563  1.1  mrg     {
    564  1.1  mrg       if (!reload_completed
    565  1.1  mrg 	  && recog_memoized (insn) >= 0
    566  1.1  mrg 	  && get_attr_type (insn) == TYPE_CMP)
    567  1.1  mrg 	{
    568  1.1  mrg 	  rtx pat = PATTERN (insn);
    569  1.1  mrg 	  gcc_assert (GET_CODE (pat) == SET);
    570  1.1  mrg 	  rtx src = SET_SRC (pat);
    571  1.1  mrg 
    572  1.1  mrg 	  /* Only the branches can be modified by the postreload compare
    573  1.1  mrg 	     elimination pass, not the cstores because they accept only
    574  1.1  mrg 	     unsigned comparison operators and they are eliminated if
    575  1.1  mrg 	     one of the operands is zero.  */
    576  1.1  mrg 	  if (GET_CODE (src) == IF_THEN_ELSE
    577  1.1  mrg 	      && XEXP (XEXP (src, 0), 1) == const0_rtx
    578  1.1  mrg 	      && recog_memoized (dep_insn) >= 0)
    579  1.1  mrg 	    {
    580  1.1  mrg 	      enum attr_type dep_attr_type = get_attr_type (dep_insn);
    581  1.1  mrg 
    582  1.1  mrg 	      /* The logical instructions use CCmode and thus work with any
    583  1.1  mrg 		 comparison operator, whereas the arithmetic instructions use
    584  1.1  mrg 		 CCNZmode and thus work with only a small subset.  */
    585  1.1  mrg 	      if (dep_attr_type == TYPE_LOGIC
    586  1.1  mrg 		  || (dep_attr_type == TYPE_ARITH
    587  1.1  mrg 		      && visium_nz_comparison_operator (XEXP (src, 0),
    588  1.1  mrg 							GET_MODE
    589  1.1  mrg 							(XEXP (src, 0)))))
    590  1.1  mrg 		return 0;
    591  1.1  mrg 	    }
    592  1.1  mrg 	}
    593  1.1  mrg 
    594  1.1  mrg       return cost;
    595  1.1  mrg     }
    596  1.1  mrg 
    597  1.1  mrg   if (recog_memoized (insn) < 0)
    598  1.1  mrg     return 0;
    599  1.1  mrg 
    600  1.1  mrg   attr_type = get_attr_type (insn);
    601  1.1  mrg 
    602  1.1  mrg   /* Anti dependency: DEP_INSN reads a register that INSN writes some
    603  1.1  mrg      cycles later.  */
    604  1.1  mrg   if (dep_type == REG_DEP_ANTI)
    605  1.1  mrg     {
    606  1.1  mrg       /* On the GR5, the latency of FP instructions needs to be taken into
    607  1.1  mrg 	 account for every dependency involving a write.  */
    608  1.1  mrg       if (attr_type == TYPE_REG_FP && visium_cpu == PROCESSOR_GR5)
    609  1.1  mrg 	{
    610  1.1  mrg 	  /* INSN is FLOAD. */
    611  1.1  mrg 	  rtx pat = PATTERN (insn);
    612  1.1  mrg 	  rtx dep_pat = PATTERN (dep_insn);
    613  1.1  mrg 
    614  1.1  mrg 	  if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
    615  1.1  mrg 	    /* If this happens, we have to extend this to schedule
    616  1.1  mrg 	       optimally. Return 0 for now. */
    617  1.1  mrg 	    return 0;
    618  1.1  mrg 
    619  1.1  mrg 	  if (reg_mentioned_p (SET_DEST (pat), SET_SRC (dep_pat)))
    620  1.1  mrg 	    {
    621  1.1  mrg 	      if (recog_memoized (dep_insn) < 0)
    622  1.1  mrg 		return 0;
    623  1.1  mrg 
    624  1.1  mrg 	      switch (get_attr_type (dep_insn))
    625  1.1  mrg 		{
    626  1.1  mrg 		case TYPE_FDIV:
    627  1.1  mrg 		case TYPE_FSQRT:
    628  1.1  mrg 		case TYPE_FTOI:
    629  1.1  mrg 		case TYPE_ITOF:
    630  1.1  mrg 		case TYPE_FP:
    631  1.1  mrg 		case TYPE_FMOVE:
    632  1.1  mrg 		  /* A fload can't be issued until a preceding arithmetic
    633  1.1  mrg 		     operation has finished if the target of the fload is
    634  1.1  mrg 		     any of the sources (or destination) of the arithmetic
    635  1.1  mrg 		     operation. Note that the latency may be (much)
    636  1.1  mrg 		     greater than this if the preceding instruction
    637  1.1  mrg 		     concerned is in a queue. */
    638  1.1  mrg 		  return insn_default_latency (dep_insn);
    639  1.1  mrg 
    640  1.1  mrg 		default:
    641  1.1  mrg 		  return 0;
    642  1.1  mrg 		}
    643  1.1  mrg 	    }
    644  1.1  mrg 	}
    645  1.1  mrg 
    646  1.1  mrg       /* On the GR6, we try to make sure that the link register is restored
    647  1.1  mrg 	 sufficiently ahead of the return as to yield a correct prediction
    648  1.1  mrg 	 from the branch predictor.  By default there is no true dependency
    649  1.1  mrg 	 but an anti dependency between them, so we simply reuse it.  */
    650  1.1  mrg       else if (attr_type == TYPE_RET && visium_cpu == PROCESSOR_GR6)
    651  1.1  mrg 	{
    652  1.1  mrg 	  rtx dep_pat = PATTERN (dep_insn);
    653  1.1  mrg 	  if (GET_CODE (dep_pat) == SET
    654  1.1  mrg 	      && REG_P (SET_DEST (dep_pat))
    655  1.1  mrg 	      && REGNO (SET_DEST (dep_pat)) == LINK_REGNUM)
    656  1.1  mrg 	    return 8;
    657  1.1  mrg 	}
    658  1.1  mrg 
    659  1.1  mrg       /* For other anti dependencies, the cost is 0. */
    660  1.1  mrg       return 0;
    661  1.1  mrg     }
    662  1.1  mrg 
    663  1.1  mrg   /* Output dependency: DEP_INSN writes a register that INSN writes some
    664  1.1  mrg      cycles later.  */
    665  1.1  mrg   else if (dep_type == REG_DEP_OUTPUT)
    666  1.1  mrg     {
    667  1.1  mrg       /* On the GR5, the latency of FP instructions needs to be taken into
    668  1.1  mrg 	 account for every dependency involving a write.  */
    669  1.1  mrg       if (attr_type == TYPE_REG_FP && visium_cpu == PROCESSOR_GR5)
    670  1.1  mrg 	{
    671  1.1  mrg 	  /* INSN is FLOAD. */
    672  1.1  mrg 	  rtx pat = PATTERN (insn);
    673  1.1  mrg 	  rtx dep_pat = PATTERN (dep_insn);
    674  1.1  mrg 
    675  1.1  mrg 	  if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
    676  1.1  mrg 	    /* If this happens, we have to extend this to schedule
    677  1.1  mrg 	       optimally. Return 0 for now. */
    678  1.1  mrg 	    return 0;
    679  1.1  mrg 
    680  1.1  mrg 	  if (reg_mentioned_p (SET_DEST (pat), SET_DEST (dep_pat)))
    681  1.1  mrg 	    {
    682  1.1  mrg 	      if (recog_memoized (dep_insn) < 0)
    683  1.1  mrg 		return 0;
    684  1.1  mrg 
    685  1.1  mrg 	      switch (get_attr_type (dep_insn))
    686  1.1  mrg 		{
    687  1.1  mrg 		case TYPE_FDIV:
    688  1.1  mrg 		case TYPE_FSQRT:
    689  1.1  mrg 		case TYPE_FTOI:
    690  1.1  mrg 		case TYPE_ITOF:
    691  1.1  mrg 		case TYPE_FP:
    692  1.1  mrg 		case TYPE_FMOVE:
    693  1.1  mrg 		  /* A fload can't be issued until a preceding arithmetic
    694  1.1  mrg 		     operation has finished if the target of the fload is
    695  1.1  mrg 		     the destination of the arithmetic operation. Note that
    696  1.1  mrg 		     the latency may be (much) greater than this if the
    697  1.1  mrg 		     preceding instruction concerned is in a queue. */
    698  1.1  mrg 		  return insn_default_latency (dep_insn);
    699  1.1  mrg 
    700  1.1  mrg 		default:
    701  1.1  mrg 		  return 0;
    702  1.1  mrg 		}
    703  1.1  mrg 	    }
    704  1.1  mrg 	}
    705  1.1  mrg 
    706  1.1  mrg       /* For other output dependencies, the cost is 0. */
    707  1.1  mrg       return 0;
    708  1.1  mrg     }
    709  1.1  mrg 
    710  1.1  mrg   return 0;
    711  1.1  mrg }
    712  1.1  mrg 
    713  1.1  mrg /* Handle an "interrupt_handler" attribute; arguments as in
    714  1.1  mrg    struct attribute_spec.handler.  */
    715  1.1  mrg 
    716  1.1  mrg static tree
    717  1.1  mrg visium_handle_interrupt_attr (tree *node, tree name,
    718  1.1  mrg 			      tree args ATTRIBUTE_UNUSED,
    719  1.1  mrg 			      int flags ATTRIBUTE_UNUSED,
    720  1.1  mrg 			      bool *no_add_attrs)
    721  1.1  mrg {
    722  1.1  mrg   if (TREE_CODE (*node) != FUNCTION_DECL)
    723  1.1  mrg     {
    724  1.1  mrg       warning (OPT_Wattributes, "%qE attribute only applies to functions",
    725  1.1  mrg 	       name);
    726  1.1  mrg       *no_add_attrs = true;
    727  1.1  mrg     }
    728  1.1  mrg   else if (!TARGET_SV_MODE)
    729  1.1  mrg     {
    730  1.1  mrg       error ("an interrupt handler cannot be compiled with %<-muser-mode%>");
    731  1.1  mrg       *no_add_attrs = true;
    732  1.1  mrg     }
    733  1.1  mrg 
    734  1.1  mrg   return NULL_TREE;
    735  1.1  mrg }
    736  1.1  mrg 
    737  1.1  mrg /* Return non-zero if the current function is an interrupt function.  */
    738  1.1  mrg 
    739  1.1  mrg int
    740  1.1  mrg visium_interrupt_function_p (void)
    741  1.1  mrg {
    742  1.1  mrg   return
    743  1.1  mrg     lookup_attribute ("interrupt",
    744  1.1  mrg 		      DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE;
    745  1.1  mrg }
    746  1.1  mrg 
    747  1.1  mrg /* Conditionally modify the settings of the register file.  */
    748  1.1  mrg 
    749  1.1  mrg static void
    750  1.1  mrg visium_conditional_register_usage (void)
    751  1.1  mrg {
    752  1.1  mrg   /* If the supervisor mode is disabled, mask some general registers.  */
    753  1.1  mrg   if (!TARGET_SV_MODE)
    754  1.1  mrg     {
    755  1.1  mrg       if (visium_cpu_and_features == PROCESSOR_GR5)
    756  1.1  mrg 	{
    757  1.1  mrg 	  fixed_regs[24] = 1;
    758  1.1  mrg 	  fixed_regs[25] = 1;
    759  1.1  mrg 	  fixed_regs[26] = 1;
    760  1.1  mrg 	  fixed_regs[27] = 1;
    761  1.1  mrg 	  fixed_regs[28] = 1;
    762  1.1  mrg 	  call_used_regs[24] = 0;
    763  1.1  mrg 	  call_used_regs[25] = 0;
    764  1.1  mrg 	  call_used_regs[26] = 0;
    765  1.1  mrg 	  call_used_regs[27] = 0;
    766  1.1  mrg 	  call_used_regs[28] = 0;
    767  1.1  mrg 	}
    768  1.1  mrg 
    769  1.1  mrg       fixed_regs[31] = 1;
    770  1.1  mrg       call_used_regs[31] = 0;
    771  1.1  mrg 
    772  1.1  mrg       /* We also need to change the long-branch register.  */
    773  1.1  mrg       if (visium_cpu_and_features == PROCESSOR_GR5)
    774  1.1  mrg 	long_branch_regnum = 20;
    775  1.1  mrg       else
    776  1.1  mrg 	long_branch_regnum = 28;
    777  1.1  mrg     }
    778  1.1  mrg 
    779  1.1  mrg   /* If the FPU is disabled, mask the FP registers.  */
    780  1.1  mrg   if (!TARGET_FPU)
    781  1.1  mrg     {
    782  1.1  mrg       for (int i = FP_FIRST_REGNUM; i <= FP_LAST_REGNUM; i++)
    783  1.1  mrg 	{
    784  1.1  mrg 	  fixed_regs[i] = 1;
    785  1.1  mrg 	  call_used_regs[i] = 0;
    786  1.1  mrg 	}
    787  1.1  mrg     }
    788  1.1  mrg }
    789  1.1  mrg 
    790  1.1  mrg /* Prepend to CLOBBERS hard registers that are automatically clobbered for
    791  1.1  mrg    an asm   We do this for the FLAGS to maintain source compatibility with
    792  1.1  mrg    the original cc0-based compiler.  */
    793  1.1  mrg 
    794  1.1  mrg static rtx_insn *
    795  1.1  mrg visium_md_asm_adjust (vec<rtx> & /*outputs*/, vec<rtx> & /*inputs*/,
    796  1.1  mrg 		      vec<machine_mode> & /*input_modes*/,
    797  1.1  mrg 		      vec<const char *> & /*constraints*/, vec<rtx> &clobbers,
    798  1.1  mrg 		      HARD_REG_SET &clobbered_regs, location_t /*loc*/)
    799  1.1  mrg {
    800  1.1  mrg   clobbers.safe_push (gen_rtx_REG (CCmode, FLAGS_REGNUM));
    801  1.1  mrg   SET_HARD_REG_BIT (clobbered_regs, FLAGS_REGNUM);
    802  1.1  mrg   return NULL;
    803  1.1  mrg }
    804  1.1  mrg 
    805  1.1  mrg /* Return true if X is a legitimate constant for a MODE immediate operand.
    806  1.1  mrg    X is guaranteed to satisfy the CONSTANT_P predicate.  */
    807  1.1  mrg 
    808  1.1  mrg static bool
    809  1.1  mrg visium_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED,
    810  1.1  mrg 			      rtx x ATTRIBUTE_UNUSED)
    811  1.1  mrg {
    812  1.1  mrg   return true;
    813  1.1  mrg }
    814  1.1  mrg 
    815  1.1  mrg /* Compute the alignment for a variable.  The alignment of an aggregate is
    816  1.1  mrg    set to be at least that of a scalar less than or equal to it in size.  */
    817  1.1  mrg 
    818  1.1  mrg unsigned int
    819  1.1  mrg visium_data_alignment (tree type, unsigned int align)
    820  1.1  mrg {
    821  1.1  mrg   if (AGGREGATE_TYPE_P (type)
    822  1.1  mrg       && TYPE_SIZE (type)
    823  1.1  mrg       && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST && align < 32)
    824  1.1  mrg     {
    825  1.1  mrg       if (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= 32)
    826  1.1  mrg 	return 32;
    827  1.1  mrg 
    828  1.1  mrg       if (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= 16 && align < 16)
    829  1.1  mrg 	return 16;
    830  1.1  mrg     }
    831  1.1  mrg 
    832  1.1  mrg   return align;
    833  1.1  mrg }
    834  1.1  mrg 
    835  1.1  mrg /* Implement TARGET_CONSTANT_ALIGNMENT.  */
    836  1.1  mrg 
    837  1.1  mrg static HOST_WIDE_INT
    838  1.1  mrg visium_constant_alignment (const_tree exp, HOST_WIDE_INT align)
    839  1.1  mrg {
    840  1.1  mrg   return visium_data_alignment (TREE_TYPE (exp), align);
    841  1.1  mrg }
    842  1.1  mrg 
    843  1.1  mrg /* Helper function for HARD_REGNO_RENAME_OK (FROM, TO).  Return non-zero if
    844  1.1  mrg    it is OK to rename a hard register FROM to another hard register TO.  */
    845  1.1  mrg 
    846  1.1  mrg int
    847  1.1  mrg visium_hard_regno_rename_ok (unsigned int from ATTRIBUTE_UNUSED,
    848  1.1  mrg 			     unsigned int to)
    849  1.1  mrg {
    850  1.1  mrg   /* If the function doesn't save LR, then the long-branch register will be
    851  1.1  mrg      used for long branches so we need to know whether it is live before the
    852  1.1  mrg      frame layout is computed.  */
    853  1.1  mrg   if (!current_function_saves_lr () && to == long_branch_regnum)
    854  1.1  mrg     return 0;
    855  1.1  mrg 
    856  1.1  mrg   /* Interrupt functions can only use registers that have already been
    857  1.1  mrg      saved by the prologue, even if they would normally be call-clobbered.  */
    858  1.1  mrg   if (crtl->is_leaf
    859  1.1  mrg       && !df_regs_ever_live_p (to)
    860  1.1  mrg       && visium_interrupt_function_p ())
    861  1.1  mrg     return 0;
    862  1.1  mrg 
    863  1.1  mrg   return 1;
    864  1.1  mrg }
    865  1.1  mrg 
    866  1.1  mrg /* Implement TARGET_HARD_REGNO_NREGS.  */
    867  1.1  mrg 
    868  1.1  mrg static unsigned int
    869  1.1  mrg visium_hard_regno_nregs (unsigned int regno, machine_mode mode)
    870  1.1  mrg {
    871  1.1  mrg   if (regno == MDB_REGNUM)
    872  1.1  mrg     return CEIL (GET_MODE_SIZE (mode), 2 * UNITS_PER_WORD);
    873  1.1  mrg   return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
    874  1.1  mrg }
    875  1.1  mrg 
    876  1.1  mrg /* Implement TARGET_HARD_REGNO_MODE_OK.
    877  1.1  mrg 
    878  1.1  mrg    Modes with sizes which cross from the one register class to the
    879  1.1  mrg    other cannot be allowed. Only single floats are allowed in the
    880  1.1  mrg    floating point registers, and only fixed point values in the EAM
    881  1.1  mrg    registers. */
    882  1.1  mrg 
    883  1.1  mrg static bool
    884  1.1  mrg visium_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
    885  1.1  mrg {
    886  1.1  mrg   if (GP_REGISTER_P (regno))
    887  1.1  mrg     return GP_REGISTER_P (end_hard_regno (mode, regno) - 1);
    888  1.1  mrg 
    889  1.1  mrg   if (FP_REGISTER_P (regno))
    890  1.1  mrg     return mode == SFmode || (mode == SImode && TARGET_FPU_IEEE);
    891  1.1  mrg 
    892  1.1  mrg   return (GET_MODE_CLASS (mode) == MODE_INT
    893  1.1  mrg 	  && visium_hard_regno_nregs (regno, mode) == 1);
    894  1.1  mrg }
    895  1.1  mrg 
    896  1.1  mrg /* Implement TARGET_MODES_TIEABLE_P.  */
    897  1.1  mrg 
    898  1.1  mrg static bool
    899  1.1  mrg visium_modes_tieable_p (machine_mode mode1, machine_mode mode2)
    900  1.1  mrg {
    901  1.1  mrg   return (GET_MODE_CLASS (mode1) == MODE_INT
    902  1.1  mrg 	  && GET_MODE_CLASS (mode2) == MODE_INT);
    903  1.1  mrg }
    904  1.1  mrg 
    905  1.1  mrg /* Return true if it is ok to do sibling call optimization for the specified
    906  1.1  mrg    call expression EXP.  DECL will be the called function, or NULL if this
    907  1.1  mrg    is an indirect call.  */
    908  1.1  mrg 
    909  1.1  mrg static bool
    910  1.1  mrg visium_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
    911  1.1  mrg 				tree exp ATTRIBUTE_UNUSED)
    912  1.1  mrg {
    913  1.1  mrg   return !visium_interrupt_function_p ();
    914  1.1  mrg }
    915  1.1  mrg 
    916  1.1  mrg /* Prepare operands for a move define_expand in MODE.  */
    917  1.1  mrg 
    918  1.1  mrg void
    919  1.1  mrg prepare_move_operands (rtx *operands, machine_mode mode)
    920  1.1  mrg {
    921  1.1  mrg   /* If the output is not a register, the input must be.  */
    922  1.1  mrg   if (GET_CODE (operands[0]) == MEM && !reg_or_0_operand (operands[1], mode))
    923  1.1  mrg     operands[1] = force_reg (mode, operands[1]);
    924  1.1  mrg }
    925  1.1  mrg 
    926  1.1  mrg /* Return true if the operands are valid for a simple move insn.  */
    927  1.1  mrg 
    928  1.1  mrg bool
    929  1.1  mrg ok_for_simple_move_operands (rtx *operands, machine_mode mode)
    930  1.1  mrg {
    931  1.1  mrg   /* One of the operands must be a register.  */
    932  1.1  mrg   if (!register_operand (operands[0], mode)
    933  1.1  mrg       && !reg_or_0_operand (operands[1], mode))
    934  1.1  mrg     return false;
    935  1.1  mrg 
    936  1.1  mrg   /* Once the flags are exposed, no simple moves between integer registers.  */
    937  1.1  mrg   if (visium_flags_exposed
    938  1.1  mrg       && gpc_reg_operand (operands[0], mode)
    939  1.1  mrg       && gpc_reg_operand (operands[1], mode))
    940  1.1  mrg     return false;
    941  1.1  mrg 
    942  1.1  mrg  return true;
    943  1.1  mrg }
    944  1.1  mrg 
    945  1.1  mrg /* Return true if the operands are valid for a simple move strict insn.  */
    946  1.1  mrg 
    947  1.1  mrg bool
    948  1.1  mrg ok_for_simple_move_strict_operands (rtx *operands, machine_mode mode)
    949  1.1  mrg {
    950  1.1  mrg   /* Once the flags are exposed, no simple moves between integer registers.
    951  1.1  mrg      Note that, in QImode only, a zero source counts as an integer register
    952  1.1  mrg      since it will be emitted as r0.  */
    953  1.1  mrg   if (visium_flags_exposed
    954  1.1  mrg       && gpc_reg_operand (operands[0], mode)
    955  1.1  mrg       && (gpc_reg_operand (operands[1], mode)
    956  1.1  mrg 	  || (mode == QImode && operands[1] == const0_rtx)))
    957  1.1  mrg     return false;
    958  1.1  mrg 
    959  1.1  mrg  return true;
    960  1.1  mrg }
    961  1.1  mrg 
    962  1.1  mrg /* Return true if the operands are valid for a simple arithmetic or logical
    963  1.1  mrg    insn.  */
    964  1.1  mrg 
    965  1.1  mrg bool
    966  1.1  mrg ok_for_simple_arith_logic_operands (rtx *, machine_mode)
    967  1.1  mrg {
    968  1.1  mrg   /* Once the flags are exposed, no simple arithmetic or logical operations
    969  1.1  mrg      between integer registers.  */
    970  1.1  mrg   return !visium_flags_exposed;
    971  1.1  mrg }
    972  1.1  mrg 
    973  1.1  mrg /* Return non-zero if a branch or call instruction will be emitting a nop
    974  1.1  mrg    into its delay slot.  */
    975  1.1  mrg 
    976  1.1  mrg int
    977  1.1  mrg empty_delay_slot (rtx_insn *insn)
    978  1.1  mrg {
    979  1.1  mrg   rtx seq;
    980  1.1  mrg 
    981  1.1  mrg   /* If no previous instruction (should not happen), return true.  */
    982  1.1  mrg   if (PREV_INSN (insn) == NULL)
    983  1.1  mrg     return 1;
    984  1.1  mrg 
    985  1.1  mrg   seq = NEXT_INSN (PREV_INSN (insn));
    986  1.1  mrg   if (GET_CODE (PATTERN (seq)) == SEQUENCE)
    987  1.1  mrg     return 0;
    988  1.1  mrg 
    989  1.1  mrg   return 1;
    990  1.1  mrg }
    991  1.1  mrg 
    992  1.1  mrg /* Wrapper around single_set which returns the second SET of a pair if the
    993  1.1  mrg    first SET is to the flags register.  */
    994  1.1  mrg 
    995  1.1  mrg static rtx
    996  1.1  mrg single_set_and_flags (rtx_insn *insn)
    997  1.1  mrg {
    998  1.1  mrg   if (multiple_sets (insn))
    999  1.1  mrg     {
   1000  1.1  mrg       rtx pat = PATTERN (insn);
   1001  1.1  mrg       if (XVECLEN (pat, 0) == 2
   1002  1.1  mrg 	  && GET_CODE (XVECEXP (pat, 0, 0)) == SET
   1003  1.1  mrg 	  && REG_P (SET_DEST (XVECEXP (pat, 0, 0)))
   1004  1.1  mrg 	  && REGNO (SET_DEST (XVECEXP (pat, 0, 0))) == FLAGS_REGNUM)
   1005  1.1  mrg 	return XVECEXP (pat, 0, 1);
   1006  1.1  mrg     }
   1007  1.1  mrg 
   1008  1.1  mrg   return single_set (insn);
   1009  1.1  mrg }
   1010  1.1  mrg 
   1011  1.1  mrg /* This is called with OUT_INSN an instruction setting a (base) register
   1012  1.1  mrg    and IN_INSN a read or a write.  Return 1 if these instructions together
   1013  1.1  mrg    constitute a pipeline hazard.
   1014  1.1  mrg 
   1015  1.1  mrg    On the original architecture, a pipeline data hazard occurs when the Dest
   1016  1.1  mrg    of one instruction becomes the SrcA for an immediately following READ or
   1017  1.1  mrg    WRITE instruction with a non-zero index (indexing occurs at the decode
   1018  1.1  mrg    stage and so a NOP must be inserted in-between for this to work).
   1019  1.1  mrg 
   1020  1.1  mrg    An example is:
   1021  1.1  mrg 
   1022  1.1  mrg 	move.l  r2,r1
   1023  1.1  mrg 	read.l  r4,10(r2)
   1024  1.1  mrg 
   1025  1.1  mrg    On the MCM, the non-zero index condition is lifted but the hazard is
   1026  1.1  mrg    patched up by the hardware through the injection of wait states:
   1027  1.1  mrg 
   1028  1.1  mrg         move.l  r2,r1
   1029  1.1  mrg         read.l  r4,(r2)
   1030  1.1  mrg 
   1031  1.1  mrg    We nevertheless try to schedule instructions around this.  */
   1032  1.1  mrg 
   1033  1.1  mrg int
   1034  1.1  mrg gr5_hazard_bypass_p (rtx_insn *out_insn, rtx_insn *in_insn)
   1035  1.1  mrg {
   1036  1.1  mrg   rtx out_set, in_set, dest, memexpr;
   1037  1.1  mrg   unsigned int out_reg, in_reg;
   1038  1.1  mrg 
   1039  1.1  mrg   /* A CALL is storage register class, but the link register is of no
   1040  1.1  mrg      interest here. */
   1041  1.1  mrg   if (GET_CODE (out_insn) == CALL_INSN)
   1042  1.1  mrg     return 0;
   1043  1.1  mrg 
   1044  1.1  mrg   out_set = single_set_and_flags (out_insn);
   1045  1.1  mrg   dest = SET_DEST (out_set);
   1046  1.1  mrg 
   1047  1.1  mrg   /* Should be no stall/hazard if OUT_INSN is MEM := ???.  This only
   1048  1.1  mrg      occurs prior to reload. */
   1049  1.1  mrg   if (GET_CODE (dest) == MEM)
   1050  1.1  mrg     return 0;
   1051  1.1  mrg 
   1052  1.1  mrg   if (GET_CODE (dest) == STRICT_LOW_PART)
   1053  1.1  mrg     dest = XEXP (dest, 0);
   1054  1.1  mrg   if (GET_CODE (dest) == SUBREG)
   1055  1.1  mrg     dest = SUBREG_REG (dest);
   1056  1.1  mrg   out_reg = REGNO (dest);
   1057  1.1  mrg 
   1058  1.1  mrg   in_set = single_set_and_flags (in_insn);
   1059  1.1  mrg 
   1060  1.1  mrg   /* If IN_INSN is MEM := MEM, it's the source that counts. */
   1061  1.1  mrg   if (GET_CODE (SET_SRC (in_set)) == MEM)
   1062  1.1  mrg     memexpr = XEXP (SET_SRC (in_set), 0);
   1063  1.1  mrg   else
   1064  1.1  mrg     memexpr = XEXP (SET_DEST (in_set), 0);
   1065  1.1  mrg 
   1066  1.1  mrg   if (GET_CODE (memexpr) == PLUS)
   1067  1.1  mrg     {
   1068  1.1  mrg       memexpr = XEXP (memexpr, 0);
   1069  1.1  mrg       if (GET_CODE (memexpr) == SUBREG)
   1070  1.1  mrg 	in_reg = REGNO (SUBREG_REG (memexpr));
   1071  1.1  mrg       else
   1072  1.1  mrg 	in_reg = REGNO (memexpr);
   1073  1.1  mrg 
   1074  1.1  mrg       if (in_reg == out_reg)
   1075  1.1  mrg 	return 1;
   1076  1.1  mrg     }
   1077  1.1  mrg   else if (TARGET_MCM)
   1078  1.1  mrg     {
   1079  1.1  mrg       if (GET_CODE (memexpr) == STRICT_LOW_PART)
   1080  1.1  mrg 	memexpr = XEXP (memexpr, 0);
   1081  1.1  mrg       if (GET_CODE (memexpr) == SUBREG)
   1082  1.1  mrg 	memexpr = SUBREG_REG (memexpr);
   1083  1.1  mrg       in_reg = REGNO (memexpr);
   1084  1.1  mrg 
   1085  1.1  mrg       if (in_reg == out_reg)
   1086  1.1  mrg 	return 1;
   1087  1.1  mrg     }
   1088  1.1  mrg 
   1089  1.1  mrg   return 0;
   1090  1.1  mrg }
   1091  1.1  mrg 
   1092  1.1  mrg /* Return true if INSN is an empty asm instruction.  */
   1093  1.1  mrg 
   1094  1.1  mrg static bool
   1095  1.1  mrg empty_asm_p (rtx insn)
   1096  1.1  mrg {
   1097  1.1  mrg   rtx body = PATTERN (insn);
   1098  1.1  mrg   const char *templ;
   1099  1.1  mrg 
   1100  1.1  mrg   if (GET_CODE (body) == ASM_INPUT)
   1101  1.1  mrg     templ = XSTR (body, 0);
   1102  1.1  mrg   else if (asm_noperands (body) >= 0)
   1103  1.1  mrg     templ = decode_asm_operands (body, NULL, NULL, NULL, NULL, NULL);
   1104  1.1  mrg   else
   1105  1.1  mrg     templ = NULL;
   1106  1.1  mrg 
   1107  1.1  mrg   return (templ && templ[0] == '\0');
   1108  1.1  mrg }
   1109  1.1  mrg 
   1110  1.1  mrg /* Insert a NOP immediately before INSN wherever there is a pipeline hazard.
   1111  1.1  mrg    LAST_REG records the register set in the last insn and LAST_INSN_CALL
   1112  1.1  mrg    records whether the last insn was a call insn.  */
   1113  1.1  mrg 
   1114  1.1  mrg static void
   1115  1.1  mrg gr5_avoid_hazard (rtx_insn *insn, unsigned int *last_reg, bool *last_insn_call)
   1116  1.1  mrg {
   1117  1.1  mrg   unsigned int dest_reg = 0;
   1118  1.1  mrg   rtx set;
   1119  1.1  mrg 
   1120  1.1  mrg   switch (GET_CODE (insn))
   1121  1.1  mrg     {
   1122  1.1  mrg     case CALL_INSN:
   1123  1.1  mrg       *last_reg = 0;
   1124  1.1  mrg       *last_insn_call = true;
   1125  1.1  mrg       return;
   1126  1.1  mrg 
   1127  1.1  mrg     case JUMP_INSN:
   1128  1.1  mrg       /* If this is an empty asm, just skip it.  */
   1129  1.1  mrg       if (!empty_asm_p (insn))
   1130  1.1  mrg 	{
   1131  1.1  mrg 	  *last_reg = 0;
   1132  1.1  mrg 	  *last_insn_call = false;
   1133  1.1  mrg 	}
   1134  1.1  mrg       return;
   1135  1.1  mrg 
   1136  1.1  mrg     case INSN:
   1137  1.1  mrg       /* If this is an empty asm, just skip it.  */
   1138  1.1  mrg       if (empty_asm_p (insn))
   1139  1.1  mrg 	return;
   1140  1.1  mrg       break;
   1141  1.1  mrg 
   1142  1.1  mrg     default:
   1143  1.1  mrg       return;
   1144  1.1  mrg     }
   1145  1.1  mrg 
   1146  1.1  mrg   set = single_set_and_flags (insn);
   1147  1.1  mrg   if (set != NULL_RTX)
   1148  1.1  mrg     {
   1149  1.1  mrg       rtx dest = SET_DEST (set);
   1150  1.1  mrg       const bool double_p = GET_MODE_SIZE (GET_MODE (dest)) > UNITS_PER_WORD;
   1151  1.1  mrg       rtx memrtx = NULL;
   1152  1.1  mrg 
   1153  1.1  mrg       if (GET_CODE (SET_SRC (set)) == MEM)
   1154  1.1  mrg 	{
   1155  1.1  mrg 	  memrtx = XEXP (SET_SRC (set), 0);
   1156  1.1  mrg 	  if (GET_CODE (dest) == STRICT_LOW_PART)
   1157  1.1  mrg 	    dest = XEXP (dest, 0);
   1158  1.1  mrg 	  if (REG_P (dest))
   1159  1.1  mrg 	    dest_reg = REGNO (dest);
   1160  1.1  mrg 
   1161  1.1  mrg 	  /* If this is a DI or DF mode memory to register
   1162  1.1  mrg 	     copy, then if rd = rs we get
   1163  1.1  mrg 
   1164  1.1  mrg 	     rs + 1 := 1[rs]
   1165  1.1  mrg 	     rs     :=  [rs]
   1166  1.1  mrg 
   1167  1.1  mrg 	     otherwise the order is
   1168  1.1  mrg 
   1169  1.1  mrg 	     rd     :=  [rs]
   1170  1.1  mrg 	     rd + 1 := 1[rs] */
   1171  1.1  mrg 
   1172  1.1  mrg 	  if (double_p)
   1173  1.1  mrg 	    {
   1174  1.1  mrg 	      unsigned int base_reg;
   1175  1.1  mrg 
   1176  1.1  mrg 	      if (GET_CODE (memrtx) == PLUS)
   1177  1.1  mrg 		base_reg = REGNO (XEXP (memrtx, 0));
   1178  1.1  mrg 	      else
   1179  1.1  mrg 		base_reg = REGNO (memrtx);
   1180  1.1  mrg 
   1181  1.1  mrg 	      if (dest_reg != base_reg)
   1182  1.1  mrg 		dest_reg++;
   1183  1.1  mrg 	    }
   1184  1.1  mrg 	}
   1185  1.1  mrg 
   1186  1.1  mrg       else if (GET_CODE (dest) == MEM)
   1187  1.1  mrg 	memrtx = XEXP (dest, 0);
   1188  1.1  mrg 
   1189  1.1  mrg       else if (GET_MODE_CLASS (GET_MODE (dest)) != MODE_CC)
   1190  1.1  mrg 	{
   1191  1.1  mrg 	  if (GET_CODE (dest) == STRICT_LOW_PART
   1192  1.1  mrg 	      ||GET_CODE (dest) == ZERO_EXTRACT)
   1193  1.1  mrg 	    dest = XEXP (dest, 0);
   1194  1.1  mrg 	  dest_reg = REGNO (dest);
   1195  1.1  mrg 
   1196  1.1  mrg 	  if (GET_CODE (SET_SRC (set)) == REG)
   1197  1.1  mrg 	    {
   1198  1.1  mrg 	      unsigned int srcreg = REGNO (SET_SRC (set));
   1199  1.1  mrg 
   1200  1.1  mrg 	      /* Check for rs := rs, which will be deleted.  */
   1201  1.1  mrg 	      if (srcreg == dest_reg)
   1202  1.1  mrg 		return;
   1203  1.1  mrg 
   1204  1.1  mrg 	      /* In the case of a DI or DF mode move from register to
   1205  1.1  mrg 	         register there is overlap if rd = rs + 1 in which case
   1206  1.1  mrg 	         the order of the copies is reversed :
   1207  1.1  mrg 
   1208  1.1  mrg 	         rd + 1 := rs + 1;
   1209  1.1  mrg 	         rd     := rs   */
   1210  1.1  mrg 
   1211  1.1  mrg 	      if (double_p && dest_reg != srcreg + 1)
   1212  1.1  mrg 		dest_reg++;
   1213  1.1  mrg 	    }
   1214  1.1  mrg 	}
   1215  1.1  mrg 
   1216  1.1  mrg       /* If this is the delay slot of a call insn, any register it sets
   1217  1.1  mrg          is not relevant.  */
   1218  1.1  mrg       if (*last_insn_call)
   1219  1.1  mrg 	dest_reg = 0;
   1220  1.1  mrg 
   1221  1.1  mrg       /* If the previous insn sets the value of a register, and this insn
   1222  1.1  mrg 	 uses a base register, check for the pipeline hazard where it is
   1223  1.1  mrg 	 the same register in each case.  */
   1224  1.1  mrg       if (*last_reg != 0 && memrtx != NULL_RTX)
   1225  1.1  mrg 	{
   1226  1.1  mrg 	  unsigned int reg = 0;
   1227  1.1  mrg 
   1228  1.1  mrg 	  /* Check for an index (original architecture).  */
   1229  1.1  mrg 	  if (GET_CODE (memrtx) == PLUS)
   1230  1.1  mrg 	    reg = REGNO (XEXP (memrtx, 0));
   1231  1.1  mrg 
   1232  1.1  mrg 	  /* Check for an MCM target or rs := [rs], in DI or DF mode.  */
   1233  1.1  mrg 	  else if (TARGET_MCM || (double_p && REGNO (memrtx) == dest_reg))
   1234  1.1  mrg 	    reg = REGNO (memrtx);
   1235  1.1  mrg 
   1236  1.1  mrg 	  /* Remove any pipeline hazard by inserting a NOP.  */
   1237  1.1  mrg 	  if (reg == *last_reg)
   1238  1.1  mrg 	    {
   1239  1.1  mrg 	      if (dump_file)
   1240  1.1  mrg 	        fprintf (dump_file,
   1241  1.1  mrg 			 "inserting nop before insn %d\n", INSN_UID (insn));
   1242  1.1  mrg 	      emit_insn_after (gen_hazard_nop (), prev_active_insn (insn));
   1243  1.1  mrg 	      emit_insn_after (gen_blockage (), insn);
   1244  1.1  mrg 	    }
   1245  1.1  mrg 	}
   1246  1.1  mrg 
   1247  1.1  mrg       *last_reg = dest_reg;
   1248  1.1  mrg     }
   1249  1.1  mrg 
   1250  1.1  mrg   *last_insn_call = false;
   1251  1.1  mrg }
   1252  1.1  mrg 
   1253  1.1  mrg /* Go through the instruction stream and insert nops where necessary to avoid
   1254  1.1  mrg    pipeline hazards.  There are two cases:
   1255  1.1  mrg 
   1256  1.1  mrg      1. On the original architecture, it is invalid to set the value of a
   1257  1.1  mrg 	(base) register and then use it in an address with a non-zero index
   1258  1.1  mrg 	in the next instruction.
   1259  1.1  mrg 
   1260  1.1  mrg      2. On the MCM, setting the value of a (base) register and then using
   1261  1.1  mrg 	it in address (including with zero index) in the next instruction
   1262  1.1  mrg 	will result in a pipeline stall of 3 cycles.  */
   1263  1.1  mrg 
   1264  1.1  mrg static void
   1265  1.1  mrg gr5_hazard_avoidance (void)
   1266  1.1  mrg {
   1267  1.1  mrg   unsigned int last_reg = 0;
   1268  1.1  mrg   bool last_insn_call = false;
   1269  1.1  mrg   rtx_insn *insn;
   1270  1.1  mrg 
   1271  1.1  mrg   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
   1272  1.1  mrg     if (INSN_P (insn))
   1273  1.1  mrg       {
   1274  1.1  mrg 	rtx pat = PATTERN (insn);
   1275  1.1  mrg 
   1276  1.1  mrg 	if (GET_CODE (pat) == SEQUENCE)
   1277  1.1  mrg 	  {
   1278  1.1  mrg 	    for (int i = 0; i < XVECLEN (pat, 0); i++)
   1279  1.1  mrg 	      gr5_avoid_hazard (as_a <rtx_insn *> (XVECEXP (pat, 0, i)),
   1280  1.1  mrg 				&last_reg, &last_insn_call);
   1281  1.1  mrg 	  }
   1282  1.1  mrg 
   1283  1.1  mrg 	else if (GET_CODE (insn) == CALL_INSN)
   1284  1.1  mrg 	  {
   1285  1.1  mrg 	    /* This call is going to get a nop in its delay slot.  */
   1286  1.1  mrg 	    last_reg = 0;
   1287  1.1  mrg 	    last_insn_call = false;
   1288  1.1  mrg 	  }
   1289  1.1  mrg 
   1290  1.1  mrg 	else
   1291  1.1  mrg 	  gr5_avoid_hazard (insn, &last_reg, &last_insn_call);
   1292  1.1  mrg       }
   1293  1.1  mrg 
   1294  1.1  mrg     else if (GET_CODE (insn) == BARRIER)
   1295  1.1  mrg       last_reg = 0;
   1296  1.1  mrg }
   1297  1.1  mrg 
   1298  1.1  mrg /* Perform a target-specific pass over the instruction stream.  The compiler
   1299  1.1  mrg    will run it at all optimization levels, just after the point at which it
   1300  1.1  mrg    normally does delayed-branch scheduling.  */
   1301  1.1  mrg 
   1302  1.1  mrg static unsigned int
   1303  1.1  mrg visium_reorg (void)
   1304  1.1  mrg {
   1305  1.1  mrg   if (visium_cpu == PROCESSOR_GR5)
   1306  1.1  mrg     gr5_hazard_avoidance ();
   1307  1.1  mrg 
   1308  1.1  mrg   return 0;
   1309  1.1  mrg }
   1310  1.1  mrg /* Return true if an argument must be passed by indirect reference.  */
   1311  1.1  mrg 
   1312  1.1  mrg static bool
   1313  1.1  mrg visium_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
   1314  1.1  mrg {
   1315  1.1  mrg   tree type = arg.type;
   1316  1.1  mrg   return type && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == VECTOR_TYPE);
   1317  1.1  mrg }
   1318  1.1  mrg 
   1319  1.1  mrg /* Define how arguments are passed.
   1320  1.1  mrg 
   1321  1.1  mrg    A range of general registers and floating registers is available
   1322  1.1  mrg    for passing arguments.  When the class of registers which an
   1323  1.1  mrg    argument would normally use is exhausted, that argument, is passed
   1324  1.1  mrg    in the overflow region of the stack.  No argument is split between
   1325  1.1  mrg    registers and stack.
   1326  1.1  mrg 
   1327  1.1  mrg    Arguments of type float or _Complex float go in FP registers if FP
   1328  1.1  mrg    hardware is available.  If there is no FP hardware, arguments of
   1329  1.1  mrg    type float go in general registers.  All other arguments are passed
   1330  1.1  mrg    in general registers.  */
   1331  1.1  mrg 
   1332  1.1  mrg static rtx
   1333  1.1  mrg visium_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
   1334  1.1  mrg {
   1335  1.1  mrg   int size;
   1336  1.1  mrg   CUMULATIVE_ARGS *ca = get_cumulative_args (pcum_v);
   1337  1.1  mrg 
   1338  1.1  mrg   size = (GET_MODE_SIZE (arg.mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
   1339  1.1  mrg   if (arg.end_marker_p ())
   1340  1.1  mrg     return GEN_INT (0);
   1341  1.1  mrg 
   1342  1.1  mrg   /* Scalar or complex single precision floating point arguments are returned
   1343  1.1  mrg      in floating registers.  */
   1344  1.1  mrg   if (TARGET_FPU
   1345  1.1  mrg       && ((GET_MODE_CLASS (arg.mode) == MODE_FLOAT
   1346  1.1  mrg 	   && GET_MODE_SIZE (arg.mode) <= UNITS_PER_HWFPVALUE)
   1347  1.1  mrg 	  || (GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_FLOAT
   1348  1.1  mrg 	      && GET_MODE_SIZE (arg.mode) <= UNITS_PER_HWFPVALUE * 2)))
   1349  1.1  mrg     {
   1350  1.1  mrg       if (ca->frcount + size <= MAX_ARGS_IN_FP_REGISTERS)
   1351  1.1  mrg 	return gen_rtx_REG (arg.mode, FP_ARG_FIRST + ca->frcount);
   1352  1.1  mrg       else
   1353  1.1  mrg 	return NULL_RTX;
   1354  1.1  mrg     }
   1355  1.1  mrg 
   1356  1.1  mrg   if (ca->grcount + size <= MAX_ARGS_IN_GP_REGISTERS)
   1357  1.1  mrg     return gen_rtx_REG (arg.mode, ca->grcount + GP_ARG_FIRST);
   1358  1.1  mrg 
   1359  1.1  mrg   return NULL_RTX;
   1360  1.1  mrg }
   1361  1.1  mrg 
   1362  1.1  mrg /* Update the summarizer variable pointed to by PCUM_V to advance past
   1363  1.1  mrg    argument ARG.  Once this is done, the variable CUM is suitable for
   1364  1.1  mrg    analyzing the _following_ argument with visium_function_arg.  */
   1365  1.1  mrg 
   1366  1.1  mrg static void
   1367  1.1  mrg visium_function_arg_advance (cumulative_args_t pcum_v,
   1368  1.1  mrg 			     const function_arg_info &arg)
   1369  1.1  mrg {
   1370  1.1  mrg   int size = (GET_MODE_SIZE (arg.mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
   1371  1.1  mrg   int stack_size = 0;
   1372  1.1  mrg   CUMULATIVE_ARGS *ca = get_cumulative_args (pcum_v);
   1373  1.1  mrg 
   1374  1.1  mrg   /* Scalar or complex single precision floating point arguments are returned
   1375  1.1  mrg      in floating registers.  */
   1376  1.1  mrg   if (TARGET_FPU
   1377  1.1  mrg       && ((GET_MODE_CLASS (arg.mode) == MODE_FLOAT
   1378  1.1  mrg 	   && GET_MODE_SIZE (arg.mode) <= UNITS_PER_HWFPVALUE)
   1379  1.1  mrg 	  || (GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_FLOAT
   1380  1.1  mrg 	      && GET_MODE_SIZE (arg.mode) <= UNITS_PER_HWFPVALUE * 2)))
   1381  1.1  mrg     {
   1382  1.1  mrg       if (ca->frcount + size <= MAX_ARGS_IN_FP_REGISTERS)
   1383  1.1  mrg 	ca->frcount += size;
   1384  1.1  mrg       else
   1385  1.1  mrg 	{
   1386  1.1  mrg 	  stack_size = size;
   1387  1.1  mrg 	  ca->frcount = MAX_ARGS_IN_FP_REGISTERS;
   1388  1.1  mrg 	}
   1389  1.1  mrg     }
   1390  1.1  mrg   else
   1391  1.1  mrg     {
   1392  1.1  mrg       /* Everything else goes in a general register, if enough are
   1393  1.1  mrg 	 available.  */
   1394  1.1  mrg       if (ca->grcount + size <= MAX_ARGS_IN_GP_REGISTERS)
   1395  1.1  mrg 	ca->grcount += size;
   1396  1.1  mrg       else
   1397  1.1  mrg 	{
   1398  1.1  mrg 	  stack_size = size;
   1399  1.1  mrg 	  ca->grcount = MAX_ARGS_IN_GP_REGISTERS;
   1400  1.1  mrg 	}
   1401  1.1  mrg     }
   1402  1.1  mrg 
   1403  1.1  mrg   if (arg.named)
   1404  1.1  mrg     ca->stack_words += stack_size;
   1405  1.1  mrg }
   1406  1.1  mrg 
   1407  1.1  mrg /* Specify whether to return the return value in memory.  */
   1408  1.1  mrg 
   1409  1.1  mrg static bool
   1410  1.1  mrg visium_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
   1411  1.1  mrg {
   1412  1.1  mrg   return (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == VECTOR_TYPE);
   1413  1.1  mrg }
   1414  1.1  mrg 
   1415  1.1  mrg /* Define how scalar values are returned.  */
   1416  1.1  mrg 
   1417  1.1  mrg static rtx
   1418  1.1  mrg visium_function_value_1 (machine_mode mode)
   1419  1.1  mrg {
   1420  1.1  mrg   /* Scalar or complex single precision floating point values
   1421  1.1  mrg      are returned in floating register f1.  */
   1422  1.1  mrg   if (TARGET_FPU
   1423  1.1  mrg       && ((GET_MODE_CLASS (mode) == MODE_FLOAT
   1424  1.1  mrg 	   && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE)
   1425  1.1  mrg 	  || (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
   1426  1.1  mrg 	      && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE * 2)))
   1427  1.1  mrg     return gen_rtx_REG (mode, FP_RETURN_REGNUM);
   1428  1.1  mrg 
   1429  1.1  mrg   /* All others are returned in r1.  */
   1430  1.1  mrg   return gen_rtx_REG (mode, RETURN_REGNUM);
   1431  1.1  mrg }
   1432  1.1  mrg 
   1433  1.1  mrg /* Return an RTX representing the place where a function returns or receives
   1434  1.1  mrg    a value of data type RET_TYPE.  */
   1435  1.1  mrg 
   1436  1.1  mrg static rtx
   1437  1.1  mrg visium_function_value (const_tree ret_type,
   1438  1.1  mrg 		       const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
   1439  1.1  mrg 		       bool outgoing ATTRIBUTE_UNUSED)
   1440  1.1  mrg {
   1441  1.1  mrg   return visium_function_value_1 (TYPE_MODE (ret_type));
   1442  1.1  mrg }
   1443  1.1  mrg 
   1444  1.1  mrg /* Return an RTX representing the place where the library function result will
   1445  1.1  mrg    be returned.  */
   1446  1.1  mrg 
   1447  1.1  mrg static rtx
   1448  1.1  mrg visium_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
   1449  1.1  mrg {
   1450  1.1  mrg   return visium_function_value_1 (mode);
   1451  1.1  mrg }
   1452  1.1  mrg 
   1453  1.1  mrg /* Store the anonymous register arguments into the stack so that all the
   1454  1.1  mrg    arguments appear to have been passed consecutively on the stack.  */
   1455  1.1  mrg 
   1456  1.1  mrg static void
   1457  1.1  mrg visium_setup_incoming_varargs (cumulative_args_t pcum_v,
   1458  1.1  mrg 			       const function_arg_info &arg,
   1459  1.1  mrg 			       int *pretend_size ATTRIBUTE_UNUSED,
   1460  1.1  mrg 			       int no_rtl)
   1461  1.1  mrg {
   1462  1.1  mrg   cumulative_args_t local_args_so_far;
   1463  1.1  mrg   CUMULATIVE_ARGS local_copy;
   1464  1.1  mrg   CUMULATIVE_ARGS *locargs;
   1465  1.1  mrg   int gp_saved, fp_saved, size;
   1466  1.1  mrg 
   1467  1.1  mrg   /* Create an internal cumulative_args_t pointer to internally define
   1468  1.1  mrg      storage to ensure calling TARGET_FUNCTION_ARG_ADVANCE does not
   1469  1.1  mrg      make global changes.  */
   1470  1.1  mrg   local_args_so_far.p = &local_copy;
   1471  1.1  mrg   locargs = get_cumulative_args (pcum_v);
   1472  1.1  mrg 
   1473  1.1  mrg #if CHECKING_P
   1474  1.1  mrg   local_args_so_far.magic = CUMULATIVE_ARGS_MAGIC;
   1475  1.1  mrg #endif
   1476  1.1  mrg 
   1477  1.1  mrg   local_copy.grcount = locargs->grcount;
   1478  1.1  mrg   local_copy.frcount = locargs->frcount;
   1479  1.1  mrg   local_copy.stack_words = locargs->stack_words;
   1480  1.1  mrg 
   1481  1.1  mrg   /* The caller has advanced ARGS_SO_FAR up to, but not beyond, the last named
   1482  1.1  mrg      argument.  Advance a local copy of ARGS_SO_FAR past the last "real" named
   1483  1.1  mrg      argument, to find out how many registers are left over.  */
   1484  1.1  mrg   TARGET_FUNCTION_ARG_ADVANCE (local_args_so_far, arg);
   1485  1.1  mrg 
   1486  1.1  mrg   /* Find how many registers we need to save.  */
   1487  1.1  mrg   locargs = get_cumulative_args (local_args_so_far);
   1488  1.1  mrg   gp_saved = MAX_ARGS_IN_GP_REGISTERS - locargs->grcount;
   1489  1.1  mrg   fp_saved = (TARGET_FPU ? MAX_ARGS_IN_FP_REGISTERS - locargs->frcount : 0);
   1490  1.1  mrg   size = (gp_saved * UNITS_PER_WORD) + (fp_saved * UNITS_PER_HWFPVALUE);
   1491  1.1  mrg 
   1492  1.1  mrg   if (!no_rtl && size > 0)
   1493  1.1  mrg     {
   1494  1.1  mrg       /* To avoid negative offsets, which are not valid addressing modes on
   1495  1.1  mrg 	 the Visium, we create a base register for the pretend args.  */
   1496  1.1  mrg       rtx ptr
   1497  1.1  mrg 	= force_reg (Pmode,
   1498  1.1  mrg 		     plus_constant (Pmode, virtual_incoming_args_rtx, -size));
   1499  1.1  mrg 
   1500  1.1  mrg       if (gp_saved > 0)
   1501  1.1  mrg 	{
   1502  1.1  mrg 	  rtx mem
   1503  1.1  mrg 	    = gen_rtx_MEM (BLKmode,
   1504  1.1  mrg 			   plus_constant (Pmode,
   1505  1.1  mrg 					  ptr,
   1506  1.1  mrg 					  fp_saved * UNITS_PER_HWFPVALUE));
   1507  1.1  mrg 	  MEM_NOTRAP_P (mem) = 1;
   1508  1.1  mrg 	  set_mem_alias_set (mem, get_varargs_alias_set ());
   1509  1.1  mrg 	  move_block_from_reg (locargs->grcount + GP_ARG_FIRST, mem, gp_saved);
   1510  1.1  mrg 	}
   1511  1.1  mrg 
   1512  1.1  mrg       if (fp_saved > 0)
   1513  1.1  mrg 	{
   1514  1.1  mrg 	  rtx mem = gen_rtx_MEM (BLKmode, ptr);
   1515  1.1  mrg 	  MEM_NOTRAP_P (mem) = 1;
   1516  1.1  mrg 	  set_mem_alias_set (mem, get_varargs_alias_set ());
   1517  1.1  mrg 	  gcc_assert (UNITS_PER_WORD == UNITS_PER_HWFPVALUE);
   1518  1.1  mrg 	  move_block_from_reg (locargs->frcount + FP_ARG_FIRST, mem, fp_saved);
   1519  1.1  mrg 	}
   1520  1.1  mrg     }
   1521  1.1  mrg 
   1522  1.1  mrg   visium_reg_parm_save_area_size = size;
   1523  1.1  mrg }
   1524  1.1  mrg 
   1525  1.1  mrg /* Define the `__builtin_va_list' type for the ABI.  */
   1526  1.1  mrg 
   1527  1.1  mrg static tree
   1528  1.1  mrg visium_build_builtin_va_list (void)
   1529  1.1  mrg {
   1530  1.1  mrg   tree f_ovfl, f_gbase, f_fbase, f_gbytes, f_fbytes, record;
   1531  1.1  mrg 
   1532  1.1  mrg   record = (*lang_hooks.types.make_type) (RECORD_TYPE);
   1533  1.1  mrg   f_ovfl = build_decl (BUILTINS_LOCATION, FIELD_DECL,
   1534  1.1  mrg 		       get_identifier ("__overflow_argptr"), ptr_type_node);
   1535  1.1  mrg   f_gbase = build_decl (BUILTINS_LOCATION, FIELD_DECL,
   1536  1.1  mrg 			get_identifier ("__gpr_base"), ptr_type_node);
   1537  1.1  mrg   f_fbase = build_decl (BUILTINS_LOCATION, FIELD_DECL,
   1538  1.1  mrg 			get_identifier ("__fpr_base"), ptr_type_node);
   1539  1.1  mrg   f_gbytes = build_decl (BUILTINS_LOCATION, FIELD_DECL,
   1540  1.1  mrg 			 get_identifier ("__gpr_bytes"),
   1541  1.1  mrg 			 short_unsigned_type_node);
   1542  1.1  mrg   f_fbytes = build_decl (BUILTINS_LOCATION, FIELD_DECL,
   1543  1.1  mrg 			 get_identifier ("__fpr_bytes"),
   1544  1.1  mrg 			 short_unsigned_type_node);
   1545  1.1  mrg 
   1546  1.1  mrg   DECL_FIELD_CONTEXT (f_ovfl) = record;
   1547  1.1  mrg   DECL_FIELD_CONTEXT (f_gbase) = record;
   1548  1.1  mrg   DECL_FIELD_CONTEXT (f_fbase) = record;
   1549  1.1  mrg   DECL_FIELD_CONTEXT (f_gbytes) = record;
   1550  1.1  mrg   DECL_FIELD_CONTEXT (f_fbytes) = record;
   1551  1.1  mrg   TYPE_FIELDS (record) = f_ovfl;
   1552  1.1  mrg   TREE_CHAIN (f_ovfl) = f_gbase;
   1553  1.1  mrg   TREE_CHAIN (f_gbase) = f_fbase;
   1554  1.1  mrg   TREE_CHAIN (f_fbase) = f_gbytes;
   1555  1.1  mrg   TREE_CHAIN (f_gbytes) = f_fbytes;
   1556  1.1  mrg   layout_type (record);
   1557  1.1  mrg 
   1558  1.1  mrg   return record;
   1559  1.1  mrg }
   1560  1.1  mrg 
   1561  1.1  mrg /* Implement `va_start' for varargs and stdarg.  */
   1562  1.1  mrg 
   1563  1.1  mrg static void
   1564  1.1  mrg visium_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
   1565  1.1  mrg {
   1566  1.1  mrg   const CUMULATIVE_ARGS *ca = &crtl->args.info;
   1567  1.1  mrg   int gp_saved = MAX_ARGS_IN_GP_REGISTERS - ca->grcount;
   1568  1.1  mrg   int fp_saved = (TARGET_FPU ? MAX_ARGS_IN_FP_REGISTERS - ca->frcount : 0);
   1569  1.1  mrg   int named_stack_size = ca->stack_words * UNITS_PER_WORD, offset;
   1570  1.1  mrg   tree f_ovfl, f_gbase, f_fbase, f_gbytes, f_fbytes;
   1571  1.1  mrg   tree ovfl, gbase, gbytes, fbase, fbytes, t;
   1572  1.1  mrg 
   1573  1.1  mrg   f_ovfl = TYPE_FIELDS (va_list_type_node);
   1574  1.1  mrg   f_gbase = TREE_CHAIN (f_ovfl);
   1575  1.1  mrg   f_fbase = TREE_CHAIN (f_gbase);
   1576  1.1  mrg   f_gbytes = TREE_CHAIN (f_fbase);
   1577  1.1  mrg   f_fbytes = TREE_CHAIN (f_gbytes);
   1578  1.1  mrg   ovfl = build3 (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl, NULL_TREE);
   1579  1.1  mrg   gbase = build3 (COMPONENT_REF, TREE_TYPE (f_gbase), valist, f_gbase,
   1580  1.1  mrg 		  NULL_TREE);
   1581  1.1  mrg   fbase = build3 (COMPONENT_REF, TREE_TYPE (f_fbase), valist, f_fbase,
   1582  1.1  mrg 		  NULL_TREE);
   1583  1.1  mrg   gbytes = build3 (COMPONENT_REF, TREE_TYPE (f_gbytes), valist, f_gbytes,
   1584  1.1  mrg 		   NULL_TREE);
   1585  1.1  mrg   fbytes = build3 (COMPONENT_REF, TREE_TYPE (f_fbytes), valist, f_fbytes,
   1586  1.1  mrg 		   NULL_TREE);
   1587  1.1  mrg 
   1588  1.1  mrg   /* Store the stacked vararg pointer in the OVFL member.  */
   1589  1.1  mrg   t = make_tree (TREE_TYPE (ovfl), virtual_incoming_args_rtx);
   1590  1.1  mrg   t = fold_build_pointer_plus_hwi (t, named_stack_size);
   1591  1.1  mrg   t = build2 (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
   1592  1.1  mrg   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
   1593  1.1  mrg 
   1594  1.1  mrg   /* Store the base address of the GPR save area into GBASE.  */
   1595  1.1  mrg   t = make_tree (TREE_TYPE (gbase), virtual_incoming_args_rtx);
   1596  1.1  mrg   offset = MAX_ARGS_IN_GP_REGISTERS * UNITS_PER_WORD;
   1597  1.1  mrg   t = fold_build_pointer_plus_hwi (t, -offset);
   1598  1.1  mrg   t = build2 (MODIFY_EXPR, TREE_TYPE (gbase), gbase, t);
   1599  1.1  mrg   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
   1600  1.1  mrg 
   1601  1.1  mrg   /* Store the base address of the FPR save area into FBASE.  */
   1602  1.1  mrg   if (fp_saved)
   1603  1.1  mrg     {
   1604  1.1  mrg       t = make_tree (TREE_TYPE (fbase), virtual_incoming_args_rtx);
   1605  1.1  mrg       offset = gp_saved * UNITS_PER_WORD
   1606  1.1  mrg 	         + MAX_ARGS_IN_FP_REGISTERS * UNITS_PER_HWFPVALUE;
   1607  1.1  mrg       t = fold_build_pointer_plus_hwi (t, -offset);
   1608  1.1  mrg       t = build2 (MODIFY_EXPR, TREE_TYPE (fbase), fbase, t);
   1609  1.1  mrg       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
   1610  1.1  mrg     }
   1611  1.1  mrg 
   1612  1.1  mrg   /* Fill in the GBYTES member.  */
   1613  1.1  mrg   t = build2 (MODIFY_EXPR, TREE_TYPE (gbytes), gbytes,
   1614  1.1  mrg 	      size_int (gp_saved * UNITS_PER_WORD));
   1615  1.1  mrg   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
   1616  1.1  mrg 
   1617  1.1  mrg   /* Fill in the FBYTES member.  */
   1618  1.1  mrg   t = build2 (MODIFY_EXPR, TREE_TYPE (fbytes),
   1619  1.1  mrg 	      fbytes, size_int (fp_saved * UNITS_PER_HWFPVALUE));
   1620  1.1  mrg   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
   1621  1.1  mrg }
   1622  1.1  mrg 
   1623  1.1  mrg /* Implement `va_arg'.  */
   1624  1.1  mrg 
   1625  1.1  mrg static tree
   1626  1.1  mrg visium_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
   1627  1.1  mrg 			gimple_seq *post_p)
   1628  1.1  mrg {
   1629  1.1  mrg   tree f_ovfl, f_gbase, f_fbase, f_gbytes, f_fbytes;
   1630  1.1  mrg   tree ovfl, base, bytes;
   1631  1.1  mrg   HOST_WIDE_INT size, rsize;
   1632  1.1  mrg   const bool by_reference_p = pass_va_arg_by_reference (type);
   1633  1.1  mrg   const bool float_reg_arg_p
   1634  1.1  mrg     = (TARGET_FPU && !by_reference_p
   1635  1.1  mrg        && ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT
   1636  1.1  mrg 	    && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_HWFPVALUE)
   1637  1.1  mrg 	   || (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_FLOAT
   1638  1.1  mrg 	       && (GET_MODE_SIZE (TYPE_MODE (type))
   1639  1.1  mrg 		   <= UNITS_PER_HWFPVALUE * 2))));
   1640  1.1  mrg   const int max_save_area_size
   1641  1.1  mrg     = (float_reg_arg_p ? MAX_ARGS_IN_FP_REGISTERS * UNITS_PER_HWFPVALUE
   1642  1.1  mrg        : MAX_ARGS_IN_GP_REGISTERS * UNITS_PER_WORD);
   1643  1.1  mrg   tree t, u, offs;
   1644  1.1  mrg   tree lab_false, lab_over, addr;
   1645  1.1  mrg   tree ptrtype = build_pointer_type (type);
   1646  1.1  mrg 
   1647  1.1  mrg   if (by_reference_p)
   1648  1.1  mrg     {
   1649  1.1  mrg       t = visium_gimplify_va_arg (valist, ptrtype, pre_p, post_p);
   1650  1.1  mrg       return build_va_arg_indirect_ref (t);
   1651  1.1  mrg     }
   1652  1.1  mrg 
   1653  1.1  mrg   size = int_size_in_bytes (type);
   1654  1.1  mrg   rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
   1655  1.1  mrg   f_ovfl = TYPE_FIELDS (va_list_type_node);
   1656  1.1  mrg   f_gbase = TREE_CHAIN (f_ovfl);
   1657  1.1  mrg   f_fbase = TREE_CHAIN (f_gbase);
   1658  1.1  mrg   f_gbytes = TREE_CHAIN (f_fbase);
   1659  1.1  mrg   f_fbytes = TREE_CHAIN (f_gbytes);
   1660  1.1  mrg 
   1661  1.1  mrg   /* We maintain separate pointers and offsets for floating-point and
   1662  1.1  mrg      general registers, but we need similar code in both cases.
   1663  1.1  mrg 
   1664  1.1  mrg      Let:
   1665  1.1  mrg 
   1666  1.1  mrg      BYTES be the number of unused bytes in the register save area.
   1667  1.1  mrg      BASE be the base address of the register save area.
   1668  1.1  mrg      OFFS be the current offset into the register save area. Either
   1669  1.1  mrg      MAX_ARGS_IN_GP_REGISTERS * UNITS_PER_WORD - bytes or
   1670  1.1  mrg      MAX_ARGS_IN_FP_REGISTERS * UNITS_PER_HWFPVALUE - bytes
   1671  1.1  mrg      depending upon whether the argument is in general or floating
   1672  1.1  mrg      registers.
   1673  1.1  mrg      ADDR_RTX be the address of the argument.
   1674  1.1  mrg      RSIZE be the size in bytes of the argument.
   1675  1.1  mrg      OVFL be the pointer to the stack overflow area.
   1676  1.1  mrg 
   1677  1.1  mrg      The code we want is:
   1678  1.1  mrg 
   1679  1.1  mrg      1: if (bytes >= rsize)
   1680  1.1  mrg      2:   {
   1681  1.1  mrg      3:     addr_rtx = base + offs;
   1682  1.1  mrg      4:     bytes -= rsize;
   1683  1.1  mrg      5:   }
   1684  1.1  mrg      6: else
   1685  1.1  mrg      7:   {
   1686  1.1  mrg      8:     bytes = 0;
   1687  1.1  mrg      9:     addr_rtx = ovfl;
   1688  1.1  mrg      10:    ovfl += rsize;
   1689  1.1  mrg      11:  }
   1690  1.1  mrg 
   1691  1.1  mrg    */
   1692  1.1  mrg 
   1693  1.1  mrg   addr = create_tmp_var (ptr_type_node, "addr");
   1694  1.1  mrg   lab_false = create_artificial_label (UNKNOWN_LOCATION);
   1695  1.1  mrg   lab_over = create_artificial_label (UNKNOWN_LOCATION);
   1696  1.1  mrg   if (float_reg_arg_p)
   1697  1.1  mrg     bytes = build3 (COMPONENT_REF, TREE_TYPE (f_fbytes), unshare_expr (valist),
   1698  1.1  mrg 		    f_fbytes, NULL_TREE);
   1699  1.1  mrg   else
   1700  1.1  mrg     bytes = build3 (COMPONENT_REF, TREE_TYPE (f_gbytes), unshare_expr (valist),
   1701  1.1  mrg 		    f_gbytes, NULL_TREE);
   1702  1.1  mrg 
   1703  1.1  mrg   /* [1] Emit code to branch if bytes < rsize.  */
   1704  1.1  mrg   t = fold_convert (TREE_TYPE (bytes), size_int (rsize));
   1705  1.1  mrg   t = build2 (LT_EXPR, boolean_type_node, bytes, t);
   1706  1.1  mrg   u = build1 (GOTO_EXPR, void_type_node, lab_false);
   1707  1.1  mrg   t = build3 (COND_EXPR, void_type_node, t, u, NULL_TREE);
   1708  1.1  mrg   gimplify_and_add (t, pre_p);
   1709  1.1  mrg 
   1710  1.1  mrg   /* [3] Emit code for: addr_rtx = base + offs, where
   1711  1.1  mrg      offs = max_save_area_size - bytes.  */
   1712  1.1  mrg   t = fold_convert (sizetype, bytes);
   1713  1.1  mrg   offs = build2 (MINUS_EXPR, sizetype, size_int (max_save_area_size), t);
   1714  1.1  mrg   if (float_reg_arg_p)
   1715  1.1  mrg     base = build3 (COMPONENT_REF, TREE_TYPE (f_fbase), valist, f_fbase,
   1716  1.1  mrg 		   NULL_TREE);
   1717  1.1  mrg   else
   1718  1.1  mrg     base = build3 (COMPONENT_REF, TREE_TYPE (f_gbase), valist, f_gbase,
   1719  1.1  mrg 		   NULL_TREE);
   1720  1.1  mrg 
   1721  1.1  mrg   t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (base), base, offs);
   1722  1.1  mrg   t = build2 (MODIFY_EXPR, void_type_node, addr, t);
   1723  1.1  mrg   gimplify_and_add (t, pre_p);
   1724  1.1  mrg 
   1725  1.1  mrg   /* [4] Emit code for: bytes -= rsize. */
   1726  1.1  mrg   t = fold_convert (TREE_TYPE (bytes), size_int (rsize));
   1727  1.1  mrg   t = build2 (MINUS_EXPR, TREE_TYPE (bytes), bytes, t);
   1728  1.1  mrg   t = build2 (MODIFY_EXPR, TREE_TYPE (bytes), bytes, t);
   1729  1.1  mrg   gimplify_and_add (t, pre_p);
   1730  1.1  mrg 
   1731  1.1  mrg   /* [6] Emit code to branch over the else clause, then the label.  */
   1732  1.1  mrg   t = build1 (GOTO_EXPR, void_type_node, lab_over);
   1733  1.1  mrg   gimplify_and_add (t, pre_p);
   1734  1.1  mrg   t = build1 (LABEL_EXPR, void_type_node, lab_false);
   1735  1.1  mrg   gimplify_and_add (t, pre_p);
   1736  1.1  mrg 
   1737  1.1  mrg   /* [8] Emit code for: bytes = 0. */
   1738  1.1  mrg   t = fold_convert (TREE_TYPE (bytes), size_int (0));
   1739  1.1  mrg   t = build2 (MODIFY_EXPR, TREE_TYPE (bytes), unshare_expr (bytes), t);
   1740  1.1  mrg   gimplify_and_add (t, pre_p);
   1741  1.1  mrg 
   1742  1.1  mrg   /* [9] Emit code for: addr_rtx = ovfl. */
   1743  1.1  mrg   ovfl = build3 (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl, NULL_TREE);
   1744  1.1  mrg   t = build2 (MODIFY_EXPR, void_type_node, addr, ovfl);
   1745  1.1  mrg   gimplify_and_add (t, pre_p);
   1746  1.1  mrg 
   1747  1.1  mrg   /* [10] Emit code for: ovfl += rsize. */
   1748  1.1  mrg   t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (ovfl), ovfl, size_int (rsize));
   1749  1.1  mrg   t = build2 (MODIFY_EXPR, TREE_TYPE (ovfl), unshare_expr (ovfl), t);
   1750  1.1  mrg   gimplify_and_add (t, pre_p);
   1751  1.1  mrg   t = build1 (LABEL_EXPR, void_type_node, lab_over);
   1752  1.1  mrg   gimplify_and_add (t, pre_p);
   1753  1.1  mrg 
   1754  1.1  mrg   /* Emit a big-endian correction if size < UNITS_PER_WORD.  */
   1755  1.1  mrg   if (size < UNITS_PER_WORD)
   1756  1.1  mrg     {
   1757  1.1  mrg       t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (addr), addr,
   1758  1.1  mrg 		  size_int (UNITS_PER_WORD - size));
   1759  1.1  mrg       t = build2 (MODIFY_EXPR, void_type_node, addr, t);
   1760  1.1  mrg       gimplify_and_add (t, pre_p);
   1761  1.1  mrg     }
   1762  1.1  mrg 
   1763  1.1  mrg   addr = fold_convert (ptrtype, addr);
   1764  1.1  mrg 
   1765  1.1  mrg   return build_va_arg_indirect_ref (addr);
   1766  1.1  mrg }
   1767  1.1  mrg 
   1768  1.1  mrg /* Return true if OP is an offset suitable for use as a displacement in the
   1769  1.1  mrg    address of a memory access in mode MODE.  */
   1770  1.1  mrg 
   1771  1.1  mrg static bool
   1772  1.1  mrg rtx_ok_for_offset_p (machine_mode mode, rtx op)
   1773  1.1  mrg {
   1774  1.1  mrg   if (!CONST_INT_P (op) || INTVAL (op) < 0)
   1775  1.1  mrg     return false;
   1776  1.1  mrg 
   1777  1.1  mrg   switch (mode)
   1778  1.1  mrg     {
   1779  1.1  mrg     case E_QImode:
   1780  1.1  mrg       return INTVAL (op) <= 31;
   1781  1.1  mrg 
   1782  1.1  mrg     case E_HImode:
   1783  1.1  mrg       return (INTVAL (op) % 2) == 0 && INTVAL (op) < 63;
   1784  1.1  mrg 
   1785  1.1  mrg     case E_SImode:
   1786  1.1  mrg     case E_SFmode:
   1787  1.1  mrg       return (INTVAL (op) % 4) == 0 && INTVAL (op) < 127;
   1788  1.1  mrg 
   1789  1.1  mrg     case E_DImode:
   1790  1.1  mrg     case E_DFmode:
   1791  1.1  mrg       return (INTVAL (op) % 4) == 0 && INTVAL (op) < 123;
   1792  1.1  mrg 
   1793  1.1  mrg     default:
   1794  1.1  mrg       return false;
   1795  1.1  mrg     }
   1796  1.1  mrg }
   1797  1.1  mrg 
   1798  1.1  mrg /* Return whether X is a legitimate memory address for a memory operand
   1799  1.1  mrg    of mode MODE.
   1800  1.1  mrg 
   1801  1.1  mrg    Legitimate addresses are defined in two variants: a strict variant
   1802  1.1  mrg    and a non-strict one.  The STRICT parameter chooses which variant
   1803  1.1  mrg    is desired by the caller.
   1804  1.1  mrg 
   1805  1.1  mrg    The strict variant is used in the reload pass.  It must be defined
   1806  1.1  mrg    so that any pseudo-register that has not been allocated a hard
   1807  1.1  mrg    register is considered a memory reference.  This is because in
   1808  1.1  mrg    contexts where some kind of register is required, a
   1809  1.1  mrg    pseudo-register with no hard register must be rejected.  For
   1810  1.1  mrg    non-hard registers, the strict variant should look up the
   1811  1.1  mrg    `reg_renumber' array; it should then proceed using the hard
   1812  1.1  mrg    register number in the array, or treat the pseudo as a memory
   1813  1.1  mrg    reference if the array holds `-1'.
   1814  1.1  mrg 
   1815  1.1  mrg    The non-strict variant is used in other passes.  It must be
   1816  1.1  mrg    defined to accept all pseudo-registers in every context where some
   1817  1.1  mrg    kind of register is required.  */
   1818  1.1  mrg 
   1819  1.1  mrg static bool
   1820  1.1  mrg visium_legitimate_address_p (machine_mode mode, rtx x, bool strict)
   1821  1.1  mrg {
   1822  1.1  mrg   rtx base;
   1823  1.1  mrg   unsigned int regno;
   1824  1.1  mrg 
   1825  1.1  mrg   /* If X is base+disp, check that we have an appropriate offset.  */
   1826  1.1  mrg   if (GET_CODE (x) == PLUS)
   1827  1.1  mrg     {
   1828  1.1  mrg       if (!rtx_ok_for_offset_p (mode, XEXP (x, 1)))
   1829  1.1  mrg 	return false;
   1830  1.1  mrg       base = XEXP (x, 0);
   1831  1.1  mrg     }
   1832  1.1  mrg   else
   1833  1.1  mrg     base = x;
   1834  1.1  mrg 
   1835  1.1  mrg   /* Now check the base: it must be either a register or a subreg thereof.  */
   1836  1.1  mrg   if (GET_CODE (base) == SUBREG)
   1837  1.1  mrg     base = SUBREG_REG (base);
   1838  1.1  mrg   if (!REG_P (base))
   1839  1.1  mrg     return false;
   1840  1.1  mrg 
   1841  1.1  mrg   regno = REGNO (base);
   1842  1.1  mrg 
   1843  1.1  mrg   /* For the strict variant, the register must be REGNO_OK_FOR_BASE_P.  */
   1844  1.1  mrg   if (strict)
   1845  1.1  mrg     return REGNO_OK_FOR_BASE_P (regno);
   1846  1.1  mrg 
   1847  1.1  mrg   /* For the non-strict variant, the register may also be a pseudo.  */
   1848  1.1  mrg   return BASE_REGISTER_P (regno) || regno >= FIRST_PSEUDO_REGISTER;
   1849  1.1  mrg }
   1850  1.1  mrg 
   1851  1.1  mrg /* Try machine-dependent ways of modifying an illegitimate address
   1852  1.1  mrg    to be legitimate.  If we find one, return the new, valid address.
   1853  1.1  mrg    This macro is used in only one place: `memory_address' in explow.cc.
   1854  1.1  mrg 
   1855  1.1  mrg    OLDX is the address as it was before break_out_memory_refs was called.
   1856  1.1  mrg    In some cases it is useful to look at this to decide what needs to be done.
   1857  1.1  mrg 
   1858  1.1  mrg    MODE and WIN are passed so that this macro can use
   1859  1.1  mrg    GO_IF_LEGITIMATE_ADDRESS.
   1860  1.1  mrg 
   1861  1.1  mrg    It is always safe for this macro to do nothing.  It exists to recognize
   1862  1.1  mrg    opportunities to optimize the output.
   1863  1.1  mrg 
   1864  1.1  mrg    For Visium
   1865  1.1  mrg 
   1866  1.1  mrg 	memory (reg + <out of range int>)
   1867  1.1  mrg 
   1868  1.1  mrg    is transformed to
   1869  1.1  mrg 
   1870  1.1  mrg 	base_int = <out of range int> & ~mask
   1871  1.1  mrg         ptr_reg = reg + base_int
   1872  1.1  mrg         memory (ptr_reg + <out of range int> - base_int)
   1873  1.1  mrg 
   1874  1.1  mrg    Thus ptr_reg is a base register for a range of addresses,
   1875  1.1  mrg    which should help CSE.
   1876  1.1  mrg 
   1877  1.1  mrg    For a 1 byte reference mask is 0x1f
   1878  1.1  mrg    for a 2 byte reference mask is 0x3f
   1879  1.1  mrg    For a 4 byte reference mask is 0x7f
   1880  1.1  mrg 
   1881  1.1  mrg    This reflects the indexing range of the processor.
   1882  1.1  mrg 
   1883  1.1  mrg    For a > 4 byte reference the mask is 0x7f provided all of the words
   1884  1.1  mrg    can be accessed with the base address obtained.  Otherwise a mask
   1885  1.1  mrg    of 0x3f is used.
   1886  1.1  mrg 
   1887  1.1  mrg    On rare occasions an unaligned base register value with an
   1888  1.1  mrg    unaligned offset is generated. Unaligned offsets are left alone for
   1889  1.1  mrg    this reason. */
   1890  1.1  mrg 
   1891  1.1  mrg static rtx
   1892  1.1  mrg visium_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
   1893  1.1  mrg 			   machine_mode mode)
   1894  1.1  mrg {
   1895  1.1  mrg   if (GET_CODE (x) == PLUS
   1896  1.1  mrg       && GET_CODE (XEXP (x, 1)) == CONST_INT
   1897  1.1  mrg       && GET_CODE (XEXP (x, 0)) == REG && mode != BLKmode)
   1898  1.1  mrg     {
   1899  1.1  mrg       int offset = INTVAL (XEXP (x, 1));
   1900  1.1  mrg       int size = GET_MODE_SIZE (mode);
   1901  1.1  mrg       int mask = (size == 1 ? 0x1f : (size == 2 ? 0x3f : 0x7f));
   1902  1.1  mrg       int mask1 = (size == 1 ? 0 : (size == 2 ? 1 : 3));
   1903  1.1  mrg       int offset_base = offset & ~mask;
   1904  1.1  mrg 
   1905  1.1  mrg       /* Check that all of the words can be accessed.  */
   1906  1.1  mrg       if (size > 4 && size + offset - offset_base > 0x80)
   1907  1.1  mrg 	offset_base = offset & ~0x3f;
   1908  1.1  mrg       if (offset_base != 0 && offset_base != offset && (offset & mask1) == 0)
   1909  1.1  mrg 	{
   1910  1.1  mrg 	  rtx ptr_reg = force_reg (Pmode,
   1911  1.1  mrg 				   gen_rtx_PLUS (Pmode,
   1912  1.1  mrg 						 XEXP (x, 0),
   1913  1.1  mrg 						 GEN_INT (offset_base)));
   1914  1.1  mrg 
   1915  1.1  mrg 	  return plus_constant (Pmode, ptr_reg, offset - offset_base);
   1916  1.1  mrg 	}
   1917  1.1  mrg     }
   1918  1.1  mrg 
   1919  1.1  mrg   return x;
   1920  1.1  mrg }
   1921  1.1  mrg 
   1922  1.1  mrg /* Perform a similar function to visium_legitimize_address, but this time
   1923  1.1  mrg    for reload.  Generating new registers is not an option here.  Parts
   1924  1.1  mrg    that need reloading are indicated by calling push_reload.  */
   1925  1.1  mrg 
   1926  1.1  mrg rtx
   1927  1.1  mrg visium_legitimize_reload_address (rtx x, machine_mode mode, int opnum,
   1928  1.1  mrg 				  int type, int ind ATTRIBUTE_UNUSED)
   1929  1.1  mrg {
   1930  1.1  mrg   rtx newrtx, tem = NULL_RTX;
   1931  1.1  mrg 
   1932  1.1  mrg   if (mode == BLKmode)
   1933  1.1  mrg     return NULL_RTX;
   1934  1.1  mrg 
   1935  1.1  mrg   if (optimize && GET_CODE (x) == PLUS)
   1936  1.1  mrg     tem = simplify_binary_operation (PLUS, GET_MODE (x), XEXP (x, 0),
   1937  1.1  mrg 				     XEXP (x, 1));
   1938  1.1  mrg 
   1939  1.1  mrg   newrtx = tem ? tem : x;
   1940  1.1  mrg   if (GET_CODE (newrtx) == PLUS
   1941  1.1  mrg       && GET_CODE (XEXP (newrtx, 1)) == CONST_INT
   1942  1.1  mrg       && GET_CODE (XEXP (newrtx, 0)) == REG
   1943  1.1  mrg       && BASE_REGISTER_P (REGNO (XEXP (newrtx, 0))))
   1944  1.1  mrg     {
   1945  1.1  mrg       int offset = INTVAL (XEXP (newrtx, 1));
   1946  1.1  mrg       int size = GET_MODE_SIZE (mode);
   1947  1.1  mrg       int mask = (size == 1 ? 0x1f : (size == 2 ? 0x3f : 0x7f));
   1948  1.1  mrg       int mask1 = (size == 1 ? 0 : (size == 2 ? 1 : 3));
   1949  1.1  mrg       int offset_base = offset & ~mask;
   1950  1.1  mrg 
   1951  1.1  mrg       /* Check that all of the words can be accessed.  */
   1952  1.1  mrg       if (size > 4 && size + offset - offset_base > 0x80)
   1953  1.1  mrg 	offset_base = offset & ~0x3f;
   1954  1.1  mrg 
   1955  1.1  mrg       if (offset_base && (offset & mask1) == 0)
   1956  1.1  mrg 	{
   1957  1.1  mrg 	  rtx temp = gen_rtx_PLUS (Pmode,
   1958  1.1  mrg 				   XEXP (newrtx, 0), GEN_INT (offset_base));
   1959  1.1  mrg 
   1960  1.1  mrg 	  x = gen_rtx_PLUS (Pmode, temp, GEN_INT (offset - offset_base));
   1961  1.1  mrg 	  push_reload (XEXP (x, 0), 0, &XEXP (x, 0), 0,
   1962  1.1  mrg 		       BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, opnum,
   1963  1.1  mrg 		       (enum reload_type) type);
   1964  1.1  mrg 	  return x;
   1965  1.1  mrg 	}
   1966  1.1  mrg     }
   1967  1.1  mrg 
   1968  1.1  mrg   return NULL_RTX;
   1969  1.1  mrg }
   1970  1.1  mrg 
   1971  1.1  mrg /* Return the cost of moving data of mode MODE from a register in class FROM to
   1972  1.1  mrg    one in class TO.  A value of 2 is the default; other values are interpreted
   1973  1.1  mrg    relative to that.  */
   1974  1.1  mrg 
   1975  1.1  mrg static int
   1976  1.1  mrg visium_register_move_cost (machine_mode mode, reg_class_t from,
   1977  1.1  mrg 			   reg_class_t to)
   1978  1.1  mrg {
   1979  1.1  mrg   const int numwords = (GET_MODE_SIZE (mode) <= UNITS_PER_WORD) ? 1 : 2;
   1980  1.1  mrg 
   1981  1.1  mrg   if (from == MDB || to == MDB)
   1982  1.1  mrg     return 4;
   1983  1.1  mrg   else if (from == MDC || to == MDC || (from == FP_REGS) != (to == FP_REGS))
   1984  1.1  mrg     return 4 * numwords;
   1985  1.1  mrg   else
   1986  1.1  mrg     return 2 * numwords;
   1987  1.1  mrg }
   1988  1.1  mrg 
   1989  1.1  mrg /* Return the cost of moving data of mode MODE between a register of class
   1990  1.1  mrg    CLASS and memory.  IN is zero if the value is to be written to memory,
   1991  1.1  mrg    non-zero if it is to be read in.  This cost is relative to those in
   1992  1.1  mrg    visium_register_move_cost.  */
   1993  1.1  mrg 
   1994  1.1  mrg static int
   1995  1.1  mrg visium_memory_move_cost (machine_mode mode,
   1996  1.1  mrg 			 reg_class_t to ATTRIBUTE_UNUSED,
   1997  1.1  mrg 			 bool in)
   1998  1.1  mrg {
   1999  1.1  mrg   /* Moving data in can be from PROM and this is expensive.  */
   2000  1.1  mrg   if (in)
   2001  1.1  mrg     {
   2002  1.1  mrg       if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
   2003  1.1  mrg 	return 7;
   2004  1.1  mrg       else
   2005  1.1  mrg 	return 13;
   2006  1.1  mrg     }
   2007  1.1  mrg 
   2008  1.1  mrg   /* Moving data out is mostly to RAM and should be cheaper.  */
   2009  1.1  mrg   else
   2010  1.1  mrg     {
   2011  1.1  mrg       if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
   2012  1.1  mrg 	return 6;
   2013  1.1  mrg       else
   2014  1.1  mrg 	return 12;
   2015  1.1  mrg     }
   2016  1.1  mrg }
   2017  1.1  mrg 
   2018  1.1  mrg /* Return the relative costs of expression X.  */
   2019  1.1  mrg 
   2020  1.1  mrg static bool
   2021  1.1  mrg visium_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
   2022  1.1  mrg 		  int opno ATTRIBUTE_UNUSED, int *total,
   2023  1.1  mrg 		  bool speed ATTRIBUTE_UNUSED)
   2024  1.1  mrg {
   2025  1.1  mrg   int code = GET_CODE (x);
   2026  1.1  mrg 
   2027  1.1  mrg   switch (code)
   2028  1.1  mrg     {
   2029  1.1  mrg     case CONST_INT:
   2030  1.1  mrg       /* Small integers are as cheap as registers.  4-byte values can
   2031  1.1  mrg 	 be fetched as immediate constants - let's give that the cost
   2032  1.1  mrg 	 of an extra insn.  */
   2033  1.1  mrg       *total = COSTS_N_INSNS (!satisfies_constraint_J (x));
   2034  1.1  mrg       return true;
   2035  1.1  mrg 
   2036  1.1  mrg     case CONST:
   2037  1.1  mrg     case LABEL_REF:
   2038  1.1  mrg     case SYMBOL_REF:
   2039  1.1  mrg       *total = COSTS_N_INSNS (2);
   2040  1.1  mrg       return true;
   2041  1.1  mrg 
   2042  1.1  mrg     case CONST_DOUBLE:
   2043  1.1  mrg       {
   2044  1.1  mrg 	rtx high, low;
   2045  1.1  mrg 	split_double (x, &high, &low);
   2046  1.1  mrg 	*total =
   2047  1.1  mrg 	  COSTS_N_INSNS
   2048  1.1  mrg 	  (!satisfies_constraint_J (high) + !satisfies_constraint_J (low));
   2049  1.1  mrg 	return true;
   2050  1.1  mrg       }
   2051  1.1  mrg 
   2052  1.1  mrg     case MULT:
   2053  1.1  mrg       *total = COSTS_N_INSNS (3);
   2054  1.1  mrg       return false;
   2055  1.1  mrg 
   2056  1.1  mrg     case DIV:
   2057  1.1  mrg     case UDIV:
   2058  1.1  mrg     case MOD:
   2059  1.1  mrg     case UMOD:
   2060  1.1  mrg       if (mode == DImode)
   2061  1.1  mrg 	*total = COSTS_N_INSNS (64);
   2062  1.1  mrg       else
   2063  1.1  mrg 	*total = COSTS_N_INSNS (32);
   2064  1.1  mrg       return false;
   2065  1.1  mrg 
   2066  1.1  mrg     case PLUS:
   2067  1.1  mrg     case MINUS:
   2068  1.1  mrg     case NEG:
   2069  1.1  mrg       /* DImode operations are performed directly on the ALU.  */
   2070  1.1  mrg       if (mode == DImode)
   2071  1.1  mrg 	*total = COSTS_N_INSNS (2);
   2072  1.1  mrg       else
   2073  1.1  mrg 	*total = COSTS_N_INSNS (1);
   2074  1.1  mrg       return false;
   2075  1.1  mrg 
   2076  1.1  mrg     case ASHIFT:
   2077  1.1  mrg     case ASHIFTRT:
   2078  1.1  mrg     case LSHIFTRT:
   2079  1.1  mrg       /* DImode operations are performed on the EAM instead.  */
   2080  1.1  mrg       if (mode == DImode)
   2081  1.1  mrg 	*total = COSTS_N_INSNS (3);
   2082  1.1  mrg       else
   2083  1.1  mrg 	*total = COSTS_N_INSNS (1);
   2084  1.1  mrg       return false;
   2085  1.1  mrg 
   2086  1.1  mrg     case COMPARE:
   2087  1.1  mrg       /* This matches the btst pattern.  */
   2088  1.1  mrg       if (GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT
   2089  1.1  mrg 	  && XEXP (x, 1) == const0_rtx
   2090  1.1  mrg 	  && XEXP (XEXP (x, 0), 1) == const1_rtx
   2091  1.1  mrg 	  && satisfies_constraint_K (XEXP (XEXP (x, 0), 2)))
   2092  1.1  mrg 	*total = COSTS_N_INSNS (1);
   2093  1.1  mrg       return false;
   2094  1.1  mrg 
   2095  1.1  mrg     default:
   2096  1.1  mrg       return false;
   2097  1.1  mrg     }
   2098  1.1  mrg }
   2099  1.1  mrg 
   2100  1.1  mrg /* Split a double move of OPERANDS in MODE.  */
   2101  1.1  mrg 
   2102  1.1  mrg void
   2103  1.1  mrg visium_split_double_move (rtx *operands, machine_mode mode)
   2104  1.1  mrg {
   2105  1.1  mrg   bool swap = false;
   2106  1.1  mrg 
   2107  1.1  mrg   /* Check register to register with overlap.  */
   2108  1.1  mrg   if (GET_CODE (operands[0]) == REG
   2109  1.1  mrg        && GET_CODE (operands[1]) == REG
   2110  1.1  mrg        && REGNO (operands[0]) == REGNO (operands[1]) + 1)
   2111  1.1  mrg     swap = true;
   2112  1.1  mrg 
   2113  1.1  mrg   /* Check memory to register where the base reg overlaps the destination.  */
   2114  1.1  mrg   if (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == MEM)
   2115  1.1  mrg     {
   2116  1.1  mrg       rtx op = XEXP (operands[1], 0);
   2117  1.1  mrg 
   2118  1.1  mrg       if (GET_CODE (op) == SUBREG)
   2119  1.1  mrg 	op = SUBREG_REG (op);
   2120  1.1  mrg 
   2121  1.1  mrg       if (GET_CODE (op) == REG  && REGNO (op) == REGNO (operands[0]))
   2122  1.1  mrg 	swap = true;
   2123  1.1  mrg 
   2124  1.1  mrg       if (GET_CODE (op) == PLUS)
   2125  1.1  mrg 	{
   2126  1.1  mrg 	  rtx x = XEXP (op, 0);
   2127  1.1  mrg 	  rtx y = XEXP (op, 1);
   2128  1.1  mrg 
   2129  1.1  mrg 	  if (GET_CODE (x) == REG && REGNO (x) == REGNO (operands[0]))
   2130  1.1  mrg 	    swap = true;
   2131  1.1  mrg 
   2132  1.1  mrg 	  if (GET_CODE (y) == REG && REGNO (y) == REGNO (operands[0]))
   2133  1.1  mrg 	    swap = true;
   2134  1.1  mrg 	}
   2135  1.1  mrg     }
   2136  1.1  mrg 
   2137  1.1  mrg   if (swap)
   2138  1.1  mrg     {
   2139  1.1  mrg       operands[2] = operand_subword (operands[0], 1, 1, mode);
   2140  1.1  mrg       operands[3] = operand_subword (operands[1], 1, 1, mode);
   2141  1.1  mrg       operands[4] = operand_subword (operands[0], 0, 1, mode);
   2142  1.1  mrg       operands[5] = operand_subword (operands[1], 0, 1, mode);
   2143  1.1  mrg     }
   2144  1.1  mrg   else
   2145  1.1  mrg     {
   2146  1.1  mrg       operands[2] = operand_subword (operands[0], 0, 1, mode);
   2147  1.1  mrg       operands[3] = operand_subword (operands[1], 0, 1, mode);
   2148  1.1  mrg       operands[4] = operand_subword (operands[0], 1, 1, mode);
   2149  1.1  mrg       operands[5] = operand_subword (operands[1], 1, 1, mode);
   2150  1.1  mrg     }
   2151  1.1  mrg }
   2152  1.1  mrg 
   2153  1.1  mrg /* Split a double addition or subtraction of operands.  */
   2154  1.1  mrg 
   2155  1.1  mrg void
   2156  1.1  mrg visium_split_double_add (enum rtx_code code, rtx op0, rtx op1, rtx op2)
   2157  1.1  mrg {
   2158  1.1  mrg   rtx op3 = gen_lowpart (SImode, op0);
   2159  1.1  mrg   rtx op4 = gen_lowpart (SImode, op1);
   2160  1.1  mrg   rtx op5;
   2161  1.1  mrg   rtx op6 = gen_highpart (SImode, op0);
   2162  1.1  mrg   rtx op7 = (op1 == const0_rtx ? op1 : gen_highpart (SImode, op1));
   2163  1.1  mrg   rtx op8;
   2164  1.1  mrg   rtx x, pat, flags;
   2165  1.1  mrg 
   2166  1.1  mrg   /* If operand #2 is a small constant, then its high part is null.  */
   2167  1.1  mrg   if (CONST_INT_P (op2))
   2168  1.1  mrg     {
   2169  1.1  mrg       HOST_WIDE_INT val = INTVAL (op2);
   2170  1.1  mrg 
   2171  1.1  mrg       if (val < 0)
   2172  1.1  mrg 	{
   2173  1.1  mrg 	  code = (code == MINUS ? PLUS : MINUS);
   2174  1.1  mrg 	  val = -val;
   2175  1.1  mrg 	}
   2176  1.1  mrg 
   2177  1.1  mrg       op5 = gen_int_mode (val, SImode);
   2178  1.1  mrg       op8 = const0_rtx;
   2179  1.1  mrg     }
   2180  1.1  mrg   else
   2181  1.1  mrg     {
   2182  1.1  mrg       op5 = gen_lowpart (SImode, op2);
   2183  1.1  mrg       op8 = gen_highpart (SImode, op2);
   2184  1.1  mrg     }
   2185  1.1  mrg 
   2186  1.1  mrg   if (op4 == const0_rtx)
   2187  1.1  mrg     pat = gen_negsi2_insn_set_carry (op3, op5);
   2188  1.1  mrg   else if (code == MINUS)
   2189  1.1  mrg     pat = gen_subsi3_insn_set_carry (op3, op4, op5);
   2190  1.1  mrg   else
   2191  1.1  mrg     pat = gen_addsi3_insn_set_carry (op3, op4, op5);
   2192  1.1  mrg   emit_insn (pat);
   2193  1.1  mrg 
   2194  1.1  mrg   /* This is the plus_[plus_]sltu_flags or minus_[minus_]sltu_flags pattern.  */
   2195  1.1  mrg   if (op8 == const0_rtx)
   2196  1.1  mrg     x = op7;
   2197  1.1  mrg   else
   2198  1.1  mrg     x = gen_rtx_fmt_ee (code, SImode, op7, op8);
   2199  1.1  mrg   flags = gen_rtx_REG (CCCmode, FLAGS_REGNUM);
   2200  1.1  mrg   x = gen_rtx_fmt_ee (code, SImode, x, gen_rtx_LTU (SImode, flags, const0_rtx));
   2201  1.1  mrg   pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
   2202  1.1  mrg   XVECEXP (pat, 0, 0) = gen_rtx_SET (op6, x);
   2203  1.1  mrg   flags = gen_rtx_REG (CCmode, FLAGS_REGNUM);
   2204  1.1  mrg   XVECEXP (pat, 0, 1) = gen_rtx_CLOBBER (VOIDmode, flags);
   2205  1.1  mrg   emit_insn (pat);
   2206  1.1  mrg 
   2207  1.1  mrg   visium_flags_exposed = true;
   2208  1.1  mrg }
   2209  1.1  mrg 
   2210  1.1  mrg /* Expand a copysign of OPERANDS in MODE.  */
   2211  1.1  mrg 
   2212  1.1  mrg void
   2213  1.1  mrg visium_expand_copysign (rtx *operands, machine_mode mode)
   2214  1.1  mrg {
   2215  1.1  mrg   rtx op0 = operands[0];
   2216  1.1  mrg   rtx op1 = operands[1];
   2217  1.1  mrg   rtx op2 = operands[2];
   2218  1.1  mrg   rtx mask = force_reg (SImode, GEN_INT (0x7fffffff));
   2219  1.1  mrg   rtx x;
   2220  1.1  mrg 
   2221  1.1  mrg   /* We manually handle SFmode because the abs and neg instructions of
   2222  1.1  mrg      the FPU on the MCM have a non-standard behavior wrt NaNs.  */
   2223  1.1  mrg   gcc_assert (mode == SFmode);
   2224  1.1  mrg 
   2225  1.1  mrg   /* First get all the non-sign bits of op1.  */
   2226  1.1  mrg   if (GET_CODE (op1) == CONST_DOUBLE)
   2227  1.1  mrg     {
   2228  1.1  mrg       if (real_isneg (CONST_DOUBLE_REAL_VALUE (op1)))
   2229  1.1  mrg 	op1 = simplify_unary_operation (ABS, mode, op1, mode);
   2230  1.1  mrg       if (op1 != CONST0_RTX (mode))
   2231  1.1  mrg 	{
   2232  1.1  mrg 	  long l;
   2233  1.1  mrg 	  REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op1), l);
   2234  1.1  mrg 	  op1 = force_reg (SImode, gen_int_mode (l, SImode));
   2235  1.1  mrg 	}
   2236  1.1  mrg     }
   2237  1.1  mrg   else
   2238  1.1  mrg     {
   2239  1.1  mrg       op1 = copy_to_mode_reg (SImode, gen_lowpart (SImode, op1));
   2240  1.1  mrg       op1 = force_reg (SImode, gen_rtx_AND (SImode, op1, mask));
   2241  1.1  mrg     }
   2242  1.1  mrg 
   2243  1.1  mrg   /* Then get the sign bit of op2.  */
   2244  1.1  mrg   mask = force_reg (SImode, gen_rtx_NOT (SImode, mask));
   2245  1.1  mrg   op2 = copy_to_mode_reg (SImode, gen_lowpart (SImode, op2));
   2246  1.1  mrg   op2 = force_reg (SImode, gen_rtx_AND (SImode, op2, mask));
   2247  1.1  mrg 
   2248  1.1  mrg   /* Finally OR the two values.  */
   2249  1.1  mrg   if (op1 == CONST0_RTX (SFmode))
   2250  1.1  mrg     x = op2;
   2251  1.1  mrg   else
   2252  1.1  mrg     x = force_reg (SImode, gen_rtx_IOR (SImode, op1, op2));
   2253  1.1  mrg 
   2254  1.1  mrg   /* And move the result to the destination.  */
   2255  1.1  mrg   emit_insn (gen_rtx_SET (op0, gen_lowpart (SFmode, x)));
   2256  1.1  mrg }
   2257  1.1  mrg 
   2258  1.1  mrg /* Expand a cstore of OPERANDS in MODE for EQ/NE/LTU/GTU/GEU/LEU.  We generate
   2259  1.1  mrg    the result in the C flag and use the ADC/SUBC instructions to write it into
   2260  1.1  mrg    the destination register.
   2261  1.1  mrg 
   2262  1.1  mrg    It would also be possible to implement support for LT/GT/LE/GE by means of
   2263  1.1  mrg    the RFLAG instruction followed by some shifts, but this can pessimize the
   2264  1.1  mrg    generated code.  */
   2265  1.1  mrg 
   2266  1.1  mrg void
   2267  1.1  mrg visium_expand_int_cstore (rtx *operands, machine_mode mode)
   2268  1.1  mrg {
   2269  1.1  mrg   enum rtx_code code = GET_CODE (operands[1]);
   2270  1.1  mrg   rtx op0 = operands[0], op1 = operands[2], op2 = operands[3], sltu;
   2271  1.1  mrg   bool reverse = false;
   2272  1.1  mrg 
   2273  1.1  mrg   switch (code)
   2274  1.1  mrg     {
   2275  1.1  mrg     case EQ:
   2276  1.1  mrg     case NE:
   2277  1.1  mrg       /* We use a special comparison to get the result in the C flag.  */
   2278  1.1  mrg       if (op2 != const0_rtx)
   2279  1.1  mrg 	op1 = force_reg (mode, gen_rtx_XOR (mode, op1, op2));
   2280  1.1  mrg       op1 = gen_rtx_NOT (mode, op1);
   2281  1.1  mrg       op2 = constm1_rtx;
   2282  1.1  mrg       if (code == EQ)
   2283  1.1  mrg 	reverse = true;
   2284  1.1  mrg       break;
   2285  1.1  mrg 
   2286  1.1  mrg     case LEU:
   2287  1.1  mrg     case GEU:
   2288  1.1  mrg       /* The result is naturally in the C flag modulo a couple of tricks.  */
   2289  1.1  mrg       code = reverse_condition (code);
   2290  1.1  mrg       reverse = true;
   2291  1.1  mrg 
   2292  1.1  mrg       /* ... fall through ...  */
   2293  1.1  mrg 
   2294  1.1  mrg     case LTU:
   2295  1.1  mrg     case GTU:
   2296  1.1  mrg       if (code == GTU)
   2297  1.1  mrg 	{
   2298  1.1  mrg 	  rtx tmp = op1;
   2299  1.1  mrg 	  op1 = op2;
   2300  1.1  mrg 	  op2 = tmp;
   2301  1.1  mrg 	}
   2302  1.1  mrg       break;
   2303  1.1  mrg 
   2304  1.1  mrg     default:
   2305  1.1  mrg       gcc_unreachable ();
   2306  1.1  mrg     }
   2307  1.1  mrg 
   2308  1.1  mrg   /* We need either a single ADC or a SUBC and a PLUS.  */
   2309  1.1  mrg   sltu = gen_rtx_LTU (SImode, op1, op2);
   2310  1.1  mrg 
   2311  1.1  mrg   if (reverse)
   2312  1.1  mrg     {
   2313  1.1  mrg       rtx tmp = copy_to_mode_reg (SImode, gen_rtx_NEG (SImode, sltu));
   2314  1.1  mrg       emit_insn (gen_add3_insn (op0, tmp, const1_rtx));
   2315  1.1  mrg     }
   2316  1.1  mrg   else
   2317  1.1  mrg     emit_insn (gen_rtx_SET (op0, sltu));
   2318  1.1  mrg }
   2319  1.1  mrg 
   2320  1.1  mrg /* Expand a cstore of OPERANDS in MODE for LT/GT/UNGE/UNLE.  We generate the
   2321  1.1  mrg    result in the C flag and use the ADC/SUBC instructions to write it into
   2322  1.1  mrg    the destination register.  */
   2323  1.1  mrg 
   2324  1.1  mrg void
   2325  1.1  mrg visium_expand_fp_cstore (rtx *operands,
   2326  1.1  mrg 			 machine_mode mode ATTRIBUTE_UNUSED)
   2327  1.1  mrg {
   2328  1.1  mrg   enum rtx_code code = GET_CODE (operands[1]);
   2329  1.1  mrg   rtx op0 = operands[0], op1 = operands[2], op2 = operands[3], slt;
   2330  1.1  mrg   bool reverse = false;
   2331  1.1  mrg 
   2332  1.1  mrg   switch (code)
   2333  1.1  mrg     {
   2334  1.1  mrg     case UNLE:
   2335  1.1  mrg     case UNGE:
   2336  1.1  mrg       /* The result is naturally in the C flag modulo a couple of tricks.  */
   2337  1.1  mrg       code = reverse_condition_maybe_unordered (code);
   2338  1.1  mrg       reverse = true;
   2339  1.1  mrg 
   2340  1.1  mrg       /* ... fall through ...  */
   2341  1.1  mrg 
   2342  1.1  mrg     case LT:
   2343  1.1  mrg     case GT:
   2344  1.1  mrg       if (code == GT)
   2345  1.1  mrg 	{
   2346  1.1  mrg 	  rtx tmp = op1;
   2347  1.1  mrg 	  op1 = op2;
   2348  1.1  mrg 	  op2 = tmp;
   2349  1.1  mrg 	}
   2350  1.1  mrg       break;
   2351  1.1  mrg 
   2352  1.1  mrg     default:
   2353  1.1  mrg       gcc_unreachable ();
   2354  1.1  mrg     }
   2355  1.1  mrg 
   2356  1.1  mrg   /* We need either a single ADC or a SUBC and a PLUS.  */
   2357  1.1  mrg   slt = gen_rtx_LT (SImode, op1, op2);
   2358  1.1  mrg 
   2359  1.1  mrg   if (reverse)
   2360  1.1  mrg     {
   2361  1.1  mrg       rtx tmp = copy_to_mode_reg (SImode, gen_rtx_NEG (SImode, slt));
   2362  1.1  mrg       emit_insn (gen_add3_insn (op0, tmp, const1_rtx));
   2363  1.1  mrg     }
   2364  1.1  mrg   else
   2365  1.1  mrg     emit_insn (gen_rtx_SET (op0, slt));
   2366  1.1  mrg }
   2367  1.1  mrg 
   2368  1.1  mrg /* Split a compare-and-store with CODE, operands OP2 and OP3, combined with
   2369  1.1  mrg    operation with OP_CODE, operands OP0 and OP1.  */
   2370  1.1  mrg 
   2371  1.1  mrg void
   2372  1.1  mrg visium_split_cstore (enum rtx_code op_code, rtx op0, rtx op1,
   2373  1.1  mrg 		     enum rtx_code code, rtx op2, rtx op3)
   2374  1.1  mrg {
   2375  1.1  mrg   machine_mode cc_mode = visium_select_cc_mode (code, op2, op3);
   2376  1.1  mrg 
   2377  1.1  mrg   /* If a FP cstore was reversed, then it was originally UNGE/UNLE.  */
   2378  1.1  mrg   if (cc_mode == CCFPEmode && (op_code == NEG || op_code == MINUS))
   2379  1.1  mrg     cc_mode = CCFPmode;
   2380  1.1  mrg 
   2381  1.1  mrg   rtx flags = gen_rtx_REG (cc_mode, FLAGS_REGNUM);
   2382  1.1  mrg   rtx x = gen_rtx_COMPARE (cc_mode, op2, op3);
   2383  1.1  mrg   x = gen_rtx_SET (flags, x);
   2384  1.1  mrg   emit_insn (x);
   2385  1.1  mrg 
   2386  1.1  mrg   x = gen_rtx_fmt_ee (code, SImode, flags, const0_rtx);
   2387  1.1  mrg   switch (op_code)
   2388  1.1  mrg     {
   2389  1.1  mrg     case SET:
   2390  1.1  mrg       break;
   2391  1.1  mrg     case NEG:
   2392  1.1  mrg       x = gen_rtx_NEG (SImode, x);
   2393  1.1  mrg       break;
   2394  1.1  mrg     case PLUS:
   2395  1.1  mrg     case MINUS:
   2396  1.1  mrg       x = gen_rtx_fmt_ee (op_code, SImode, op1, x);
   2397  1.1  mrg       break;
   2398  1.1  mrg     default:
   2399  1.1  mrg       gcc_unreachable ();
   2400  1.1  mrg     }
   2401  1.1  mrg 
   2402  1.1  mrg   rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
   2403  1.1  mrg   XVECEXP (pat, 0, 0) = gen_rtx_SET (op0, x);
   2404  1.1  mrg   flags = gen_rtx_REG (CCmode, FLAGS_REGNUM);
   2405  1.1  mrg   XVECEXP (pat, 0, 1) = gen_rtx_CLOBBER (VOIDmode, flags);
   2406  1.1  mrg   emit_insn (pat);
   2407  1.1  mrg 
   2408  1.1  mrg   visium_flags_exposed = true;
   2409  1.1  mrg }
   2410  1.1  mrg 
   2411  1.1  mrg /* Generate a call to a library function to move BYTES_RTX bytes from SRC with
   2412  1.1  mrg    address SRC_REG to DST with address DST_REG in 4-byte chunks.  */
   2413  1.1  mrg 
   2414  1.1  mrg static void
   2415  1.1  mrg expand_block_move_4 (rtx dst, rtx dst_reg, rtx src, rtx src_reg, rtx bytes_rtx)
   2416  1.1  mrg {
   2417  1.1  mrg   unsigned HOST_WIDE_INT bytes = UINTVAL (bytes_rtx);
   2418  1.1  mrg   unsigned int rem = bytes % 4;
   2419  1.1  mrg 
   2420  1.1  mrg   if (TARGET_BMI)
   2421  1.1  mrg     {
   2422  1.1  mrg       unsigned int i;
   2423  1.1  mrg       rtx insn;
   2424  1.1  mrg 
   2425  1.1  mrg       emit_move_insn (regno_reg_rtx[1], dst_reg);
   2426  1.1  mrg       emit_move_insn (regno_reg_rtx[2], src_reg);
   2427  1.1  mrg       emit_move_insn (regno_reg_rtx[3], bytes_rtx);
   2428  1.1  mrg 
   2429  1.1  mrg       insn = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (8));
   2430  1.1  mrg       XVECEXP (insn, 0, 0)
   2431  1.1  mrg 	= gen_rtx_SET (replace_equiv_address_nv (dst, regno_reg_rtx[1]),
   2432  1.1  mrg 		       replace_equiv_address_nv (src, regno_reg_rtx[2]));
   2433  1.1  mrg       XVECEXP (insn, 0, 1) = gen_rtx_USE (VOIDmode, regno_reg_rtx[3]);
   2434  1.1  mrg       for (i = 1; i <= 6; i++)
   2435  1.1  mrg 	XVECEXP (insn, 0, 1 + i)
   2436  1.1  mrg 	  = gen_rtx_CLOBBER (VOIDmode, regno_reg_rtx[i]);
   2437  1.1  mrg       emit_insn (insn);
   2438  1.1  mrg     }
   2439  1.1  mrg   else
   2440  1.1  mrg     emit_library_call (long_int_memcpy_libfunc, LCT_NORMAL, VOIDmode,
   2441  1.1  mrg 		       dst_reg, Pmode,
   2442  1.1  mrg 		       src_reg, Pmode,
   2443  1.1  mrg 		       convert_to_mode (TYPE_MODE (sizetype),
   2444  1.1  mrg 					GEN_INT (bytes >> 2),
   2445  1.1  mrg 				        TYPE_UNSIGNED (sizetype)),
   2446  1.1  mrg 		       TYPE_MODE (sizetype));
   2447  1.1  mrg   if (rem == 0)
   2448  1.1  mrg     return;
   2449  1.1  mrg 
   2450  1.1  mrg   dst = replace_equiv_address_nv (dst, dst_reg);
   2451  1.1  mrg   src = replace_equiv_address_nv (src, src_reg);
   2452  1.1  mrg   bytes -= rem;
   2453  1.1  mrg 
   2454  1.1  mrg   if (rem > 1)
   2455  1.1  mrg     {
   2456  1.1  mrg       emit_move_insn (adjust_address_nv (dst, HImode, bytes),
   2457  1.1  mrg 		      adjust_address_nv (src, HImode, bytes));
   2458  1.1  mrg       bytes += 2;
   2459  1.1  mrg       rem -= 2;
   2460  1.1  mrg     }
   2461  1.1  mrg 
   2462  1.1  mrg   if (rem > 0)
   2463  1.1  mrg     emit_move_insn (adjust_address_nv (dst, QImode, bytes),
   2464  1.1  mrg 		    adjust_address_nv (src, QImode, bytes));
   2465  1.1  mrg }
   2466  1.1  mrg 
   2467  1.1  mrg /* Generate a call to a library function to move BYTES_RTX bytes from SRC with
   2468  1.1  mrg    address SRC_REG to DST with address DST_REG in 2-bytes chunks.  */
   2469  1.1  mrg 
   2470  1.1  mrg static void
   2471  1.1  mrg expand_block_move_2 (rtx dst, rtx dst_reg, rtx src, rtx src_reg, rtx bytes_rtx)
   2472  1.1  mrg {
   2473  1.1  mrg   unsigned HOST_WIDE_INT bytes = UINTVAL (bytes_rtx);
   2474  1.1  mrg   unsigned int rem = bytes % 2;
   2475  1.1  mrg 
   2476  1.1  mrg   emit_library_call (wrd_memcpy_libfunc, LCT_NORMAL, VOIDmode,
   2477  1.1  mrg 		     dst_reg, Pmode,
   2478  1.1  mrg 		     src_reg, Pmode,
   2479  1.1  mrg 		     convert_to_mode (TYPE_MODE (sizetype),
   2480  1.1  mrg 				      GEN_INT (bytes >> 1),
   2481  1.1  mrg 				      TYPE_UNSIGNED (sizetype)),
   2482  1.1  mrg 		     TYPE_MODE (sizetype));
   2483  1.1  mrg   if (rem == 0)
   2484  1.1  mrg     return;
   2485  1.1  mrg 
   2486  1.1  mrg   dst = replace_equiv_address_nv (dst, dst_reg);
   2487  1.1  mrg   src = replace_equiv_address_nv (src, src_reg);
   2488  1.1  mrg   bytes -= rem;
   2489  1.1  mrg 
   2490  1.1  mrg   emit_move_insn (adjust_address_nv (dst, QImode, bytes),
   2491  1.1  mrg 		  adjust_address_nv (src, QImode, bytes));
   2492  1.1  mrg }
   2493  1.1  mrg 
   2494  1.1  mrg /* Generate a call to a library function to move BYTES_RTX bytes from address
   2495  1.1  mrg    SRC_REG to address DST_REG in 1-byte chunks.  */
   2496  1.1  mrg 
   2497  1.1  mrg static void
   2498  1.1  mrg expand_block_move_1 (rtx dst_reg, rtx src_reg, rtx bytes_rtx)
   2499  1.1  mrg {
   2500  1.1  mrg   emit_library_call (byt_memcpy_libfunc, LCT_NORMAL, VOIDmode,
   2501  1.1  mrg 		     dst_reg, Pmode,
   2502  1.1  mrg 		     src_reg, Pmode,
   2503  1.1  mrg 		     convert_to_mode (TYPE_MODE (sizetype),
   2504  1.1  mrg 				      bytes_rtx,
   2505  1.1  mrg 				      TYPE_UNSIGNED (sizetype)),
   2506  1.1  mrg 		     TYPE_MODE (sizetype));
   2507  1.1  mrg }
   2508  1.1  mrg 
   2509  1.1  mrg /* Generate a call to a library function to set BYTES_RTX bytes of DST with
   2510  1.1  mrg    address DST_REG to VALUE_RTX in 4-byte chunks.  */
   2511  1.1  mrg 
   2512  1.1  mrg static void
   2513  1.1  mrg expand_block_set_4 (rtx dst, rtx dst_reg, rtx value_rtx, rtx bytes_rtx)
   2514  1.1  mrg {
   2515  1.1  mrg   unsigned HOST_WIDE_INT bytes = UINTVAL (bytes_rtx);
   2516  1.1  mrg   unsigned int rem = bytes % 4;
   2517  1.1  mrg 
   2518  1.1  mrg   value_rtx = convert_to_mode (Pmode, value_rtx, 1);
   2519  1.1  mrg   emit_library_call (long_int_memset_libfunc, LCT_NORMAL, VOIDmode,
   2520  1.1  mrg 		     dst_reg, Pmode,
   2521  1.1  mrg 		     value_rtx, Pmode,
   2522  1.1  mrg 		     convert_to_mode (TYPE_MODE (sizetype),
   2523  1.1  mrg 				      GEN_INT (bytes >> 2),
   2524  1.1  mrg 				      TYPE_UNSIGNED (sizetype)),
   2525  1.1  mrg 		     TYPE_MODE (sizetype));
   2526  1.1  mrg   if (rem == 0)
   2527  1.1  mrg     return;
   2528  1.1  mrg 
   2529  1.1  mrg   dst = replace_equiv_address_nv (dst, dst_reg);
   2530  1.1  mrg   bytes -= rem;
   2531  1.1  mrg 
   2532  1.1  mrg   if (rem > 1)
   2533  1.1  mrg     {
   2534  1.1  mrg       if (CONST_INT_P (value_rtx))
   2535  1.1  mrg 	{
   2536  1.1  mrg 	  const unsigned HOST_WIDE_INT value = UINTVAL (value_rtx) & 0xff;
   2537  1.1  mrg 	  emit_move_insn (adjust_address_nv (dst, HImode, bytes),
   2538  1.1  mrg 			  gen_int_mode ((value << 8) | value, HImode));
   2539  1.1  mrg 	}
   2540  1.1  mrg       else
   2541  1.1  mrg 	{
   2542  1.1  mrg 	  rtx temp = convert_to_mode (QImode, value_rtx, 1);
   2543  1.1  mrg 	  emit_move_insn (adjust_address_nv (dst, QImode, bytes), temp);
   2544  1.1  mrg 	  emit_move_insn (adjust_address_nv (dst, QImode, bytes + 1), temp);
   2545  1.1  mrg 	}
   2546  1.1  mrg       bytes += 2;
   2547  1.1  mrg       rem -= 2;
   2548  1.1  mrg     }
   2549  1.1  mrg 
   2550  1.1  mrg   if (rem > 0)
   2551  1.1  mrg     emit_move_insn (adjust_address_nv (dst, QImode, bytes),
   2552  1.1  mrg 		    convert_to_mode (QImode, value_rtx, 1));
   2553  1.1  mrg }
   2554  1.1  mrg 
   2555  1.1  mrg /* Generate a call to a library function to set BYTES_RTX bytes of DST with
   2556  1.1  mrg    address DST_REG to VALUE_RTX in 2-byte chunks.  */
   2557  1.1  mrg 
   2558  1.1  mrg static void
   2559  1.1  mrg expand_block_set_2 (rtx dst, rtx dst_reg, rtx value_rtx, rtx bytes_rtx)
   2560  1.1  mrg {
   2561  1.1  mrg   unsigned HOST_WIDE_INT bytes = UINTVAL (bytes_rtx);
   2562  1.1  mrg   unsigned int rem = bytes % 2;
   2563  1.1  mrg 
   2564  1.1  mrg   value_rtx = convert_to_mode (Pmode, value_rtx, 1);
   2565  1.1  mrg   emit_library_call (wrd_memset_libfunc, LCT_NORMAL, VOIDmode,
   2566  1.1  mrg 		     dst_reg, Pmode,
   2567  1.1  mrg 		     value_rtx, Pmode,
   2568  1.1  mrg 		     convert_to_mode (TYPE_MODE (sizetype),
   2569  1.1  mrg 				      GEN_INT (bytes >> 1),
   2570  1.1  mrg 				      TYPE_UNSIGNED (sizetype)),
   2571  1.1  mrg 		     TYPE_MODE (sizetype));
   2572  1.1  mrg   if (rem == 0)
   2573  1.1  mrg     return;
   2574  1.1  mrg 
   2575  1.1  mrg   dst = replace_equiv_address_nv (dst, dst_reg);
   2576  1.1  mrg   bytes -= rem;
   2577  1.1  mrg 
   2578  1.1  mrg   emit_move_insn (adjust_address_nv (dst, QImode, bytes),
   2579  1.1  mrg 		  convert_to_mode (QImode, value_rtx, 1));
   2580  1.1  mrg }
   2581  1.1  mrg 
   2582  1.1  mrg /* Generate a call to a library function to set BYTES_RTX bytes at address
   2583  1.1  mrg    DST_REG to VALUE_RTX in 1-byte chunks.  */
   2584  1.1  mrg 
   2585  1.1  mrg static void
   2586  1.1  mrg expand_block_set_1 (rtx dst_reg, rtx value_rtx, rtx bytes_rtx)
   2587  1.1  mrg {
   2588  1.1  mrg   value_rtx = convert_to_mode (Pmode, value_rtx, 1);
   2589  1.1  mrg   emit_library_call (byt_memset_libfunc, LCT_NORMAL, VOIDmode,
   2590  1.1  mrg 		     dst_reg, Pmode,
   2591  1.1  mrg 		     value_rtx, Pmode,
   2592  1.1  mrg 		     convert_to_mode (TYPE_MODE (sizetype),
   2593  1.1  mrg 				      bytes_rtx,
   2594  1.1  mrg 				      TYPE_UNSIGNED (sizetype)),
   2595  1.1  mrg 		     TYPE_MODE (sizetype));
   2596  1.1  mrg }
   2597  1.1  mrg 
   2598  1.1  mrg /* Expand string/block move operations.
   2599  1.1  mrg 
   2600  1.1  mrg    operands[0] is the pointer to the destination.
   2601  1.1  mrg    operands[1] is the pointer to the source.
   2602  1.1  mrg    operands[2] is the number of bytes to move.
   2603  1.1  mrg    operands[3] is the alignment.
   2604  1.1  mrg 
   2605  1.1  mrg    Return 1 upon success, 0 otherwise.  */
   2606  1.1  mrg 
   2607  1.1  mrg int
   2608  1.1  mrg visium_expand_block_move (rtx *operands)
   2609  1.1  mrg {
   2610  1.1  mrg   rtx dst = operands[0];
   2611  1.1  mrg   rtx src = operands[1];
   2612  1.1  mrg   rtx bytes_rtx = operands[2];
   2613  1.1  mrg   rtx align_rtx = operands[3];
   2614  1.1  mrg   const int align = INTVAL (align_rtx);
   2615  1.1  mrg   rtx dst_reg, src_reg;
   2616  1.1  mrg   tree dst_expr, src_expr;
   2617  1.1  mrg 
   2618  1.1  mrg   /* We only handle a fixed number of bytes for now.  */
   2619  1.1  mrg   if (!CONST_INT_P (bytes_rtx) || INTVAL (bytes_rtx) <= 0)
   2620  1.1  mrg     return 0;
   2621  1.1  mrg 
   2622  1.1  mrg   /* Copy the addresses into scratch registers.  */
   2623  1.1  mrg   dst_reg = copy_addr_to_reg (XEXP (dst, 0));
   2624  1.1  mrg   src_reg = copy_addr_to_reg (XEXP (src, 0));
   2625  1.1  mrg 
   2626  1.1  mrg   /* Move the data with the appropriate granularity.  */
   2627  1.1  mrg   if (align >= 4)
   2628  1.1  mrg     expand_block_move_4 (dst, dst_reg, src, src_reg, bytes_rtx);
   2629  1.1  mrg   else if (align >= 2)
   2630  1.1  mrg     expand_block_move_2 (dst, dst_reg, src, src_reg, bytes_rtx);
   2631  1.1  mrg   else
   2632  1.1  mrg     expand_block_move_1 (dst_reg, src_reg, bytes_rtx);
   2633  1.1  mrg 
   2634  1.1  mrg   /* Since DST and SRC are passed to a libcall, mark the corresponding
   2635  1.1  mrg      tree EXPR as addressable.  */
   2636  1.1  mrg   dst_expr = MEM_EXPR (dst);
   2637  1.1  mrg   src_expr = MEM_EXPR (src);
   2638  1.1  mrg   if (dst_expr)
   2639  1.1  mrg     mark_addressable (dst_expr);
   2640  1.1  mrg   if (src_expr)
   2641  1.1  mrg     mark_addressable (src_expr);
   2642  1.1  mrg 
   2643  1.1  mrg   return 1;
   2644  1.1  mrg }
   2645  1.1  mrg 
   2646  1.1  mrg /* Expand string/block set operations.
   2647  1.1  mrg 
   2648  1.1  mrg    operands[0] is the pointer to the destination.
   2649  1.1  mrg    operands[1] is the number of bytes to set.
   2650  1.1  mrg    operands[2] is the source value.
   2651  1.1  mrg    operands[3] is the alignment.
   2652  1.1  mrg 
   2653  1.1  mrg    Return 1 upon success, 0 otherwise.  */
   2654  1.1  mrg 
   2655  1.1  mrg int
   2656  1.1  mrg visium_expand_block_set (rtx *operands)
   2657  1.1  mrg {
   2658  1.1  mrg   rtx dst = operands[0];
   2659  1.1  mrg   rtx bytes_rtx = operands[1];
   2660  1.1  mrg   rtx value_rtx = operands[2];
   2661  1.1  mrg   rtx align_rtx = operands[3];
   2662  1.1  mrg   const int align = INTVAL (align_rtx);
   2663  1.1  mrg   rtx dst_reg;
   2664  1.1  mrg   tree dst_expr;
   2665  1.1  mrg 
   2666  1.1  mrg   /* We only handle a fixed number of bytes for now.  */
   2667  1.1  mrg   if (!CONST_INT_P (bytes_rtx) || INTVAL (bytes_rtx) <= 0)
   2668  1.1  mrg     return 0;
   2669  1.1  mrg 
   2670  1.1  mrg   /* Copy the address into a scratch register.  */
   2671  1.1  mrg   dst_reg = copy_addr_to_reg (XEXP (dst, 0));
   2672  1.1  mrg 
   2673  1.1  mrg   /* Set the data with the appropriate granularity.  */
   2674  1.1  mrg   if (align >= 4)
   2675  1.1  mrg     expand_block_set_4 (dst, dst_reg, value_rtx, bytes_rtx);
   2676  1.1  mrg   else if (align >= 2)
   2677  1.1  mrg     expand_block_set_2 (dst, dst_reg, value_rtx, bytes_rtx);
   2678  1.1  mrg   else
   2679  1.1  mrg     expand_block_set_1 (dst_reg, value_rtx, bytes_rtx);
   2680  1.1  mrg 
   2681  1.1  mrg   /* Since DST is passed to a libcall, mark the corresponding
   2682  1.1  mrg      tree EXPR as addressable.  */
   2683  1.1  mrg   dst_expr = MEM_EXPR (dst);
   2684  1.1  mrg   if (dst_expr)
   2685  1.1  mrg     mark_addressable (dst_expr);
   2686  1.1  mrg 
   2687  1.1  mrg   return 1;
   2688  1.1  mrg }
   2689  1.1  mrg 
   2690  1.1  mrg /* Initialize a trampoline.  M_TRAMP is an RTX for the memory block for the
   2691  1.1  mrg    trampoline, FNDECL is the FUNCTION_DECL for the nested function and
   2692  1.1  mrg    STATIC_CHAIN is an RTX for the static chain value that should be passed
   2693  1.1  mrg    to the function when it is called.  */
   2694  1.1  mrg 
   2695  1.1  mrg static void
   2696  1.1  mrg visium_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
   2697  1.1  mrg {
   2698  1.1  mrg   rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
   2699  1.1  mrg   rtx addr = XEXP (m_tramp, 0);
   2700  1.1  mrg 
   2701  1.1  mrg   /* The trampoline initialization sequence is:
   2702  1.1  mrg 
   2703  1.1  mrg 	moviu   r9,%u FUNCTION
   2704  1.1  mrg 	movil   r9,%l FUNCTION
   2705  1.1  mrg 	[nop]
   2706  1.1  mrg 	moviu   r20,%u STATIC
   2707  1.1  mrg 	bra     tr,r9,r9
   2708  1.1  mrg 	 movil   r20,%l STATIC
   2709  1.1  mrg 
   2710  1.1  mrg      We don't use r0 as the destination register of the branch because we want
   2711  1.1  mrg      the Branch Pre-decode Logic of the GR6 to use the Address Load Array to
   2712  1.1  mrg      predict the branch target.  */
   2713  1.1  mrg 
   2714  1.1  mrg   emit_move_insn (gen_rtx_MEM (SImode, plus_constant (Pmode, addr, 0)),
   2715  1.1  mrg 		  plus_constant (SImode,
   2716  1.1  mrg 				 expand_shift (RSHIFT_EXPR, SImode, fnaddr,
   2717  1.1  mrg 					       16, NULL_RTX, 1),
   2718  1.1  mrg 				 0x04a90000));
   2719  1.1  mrg 
   2720  1.1  mrg   emit_move_insn (gen_rtx_MEM (SImode, plus_constant (Pmode, addr, 4)),
   2721  1.1  mrg 		  plus_constant (SImode,
   2722  1.1  mrg 				 expand_and (SImode, fnaddr, GEN_INT (0xffff),
   2723  1.1  mrg 					     NULL_RTX),
   2724  1.1  mrg 				 0x04890000));
   2725  1.1  mrg 
   2726  1.1  mrg   if (visium_cpu == PROCESSOR_GR6)
   2727  1.1  mrg     {
   2728  1.1  mrg       /* For the GR6, the BRA insn must be aligned on a 64-bit boundary.  */
   2729  1.1  mrg       gcc_assert (TRAMPOLINE_ALIGNMENT >= 64);
   2730  1.1  mrg       emit_move_insn (gen_rtx_MEM (SImode, plus_constant (Pmode, addr, 12)),
   2731  1.1  mrg 		      gen_int_mode (0, SImode));
   2732  1.1  mrg     }
   2733  1.1  mrg 
   2734  1.1  mrg   emit_move_insn (gen_rtx_MEM (SImode, plus_constant (Pmode, addr, 8)),
   2735  1.1  mrg 		  plus_constant (SImode,
   2736  1.1  mrg 				 expand_shift (RSHIFT_EXPR, SImode,
   2737  1.1  mrg 					       static_chain,
   2738  1.1  mrg 					       16, NULL_RTX, 1),
   2739  1.1  mrg 				 0x04b40000));
   2740  1.1  mrg 
   2741  1.1  mrg   emit_move_insn (gen_rtx_MEM (SImode, plus_constant (Pmode, addr, 12)),
   2742  1.1  mrg 		  gen_int_mode (0xff892404, SImode));
   2743  1.1  mrg 
   2744  1.1  mrg   emit_move_insn (gen_rtx_MEM (SImode, plus_constant (Pmode, addr, 16)),
   2745  1.1  mrg 		  plus_constant (SImode,
   2746  1.1  mrg 				 expand_and (SImode, static_chain,
   2747  1.1  mrg 					     GEN_INT (0xffff), NULL_RTX),
   2748  1.1  mrg 				 0x04940000));
   2749  1.1  mrg 
   2750  1.1  mrg   emit_library_call (set_trampoline_parity_libfunc, LCT_NORMAL, VOIDmode,
   2751  1.1  mrg 		     addr, SImode);
   2752  1.1  mrg }
   2753  1.1  mrg 
   2754  1.1  mrg /* Return true if the current function must have and use a frame pointer.  */
   2755  1.1  mrg 
   2756  1.1  mrg static bool
   2757  1.1  mrg visium_frame_pointer_required (void)
   2758  1.1  mrg {
   2759  1.1  mrg   /* The frame pointer is required if the function isn't leaf to be able to
   2760  1.1  mrg      do manual stack unwinding.  */
   2761  1.1  mrg   if (!crtl->is_leaf)
   2762  1.1  mrg     return true;
   2763  1.1  mrg 
   2764  1.1  mrg   /* If the stack pointer is dynamically modified in the function, it cannot
   2765  1.1  mrg      serve as the frame pointer.  */
   2766  1.1  mrg   if (!crtl->sp_is_unchanging)
   2767  1.1  mrg     return true;
   2768  1.1  mrg 
   2769  1.1  mrg   /* If the function receives nonlocal gotos, it needs to save the frame
   2770  1.1  mrg      pointer in the nonlocal_goto_save_area object.  */
   2771  1.1  mrg   if (cfun->has_nonlocal_label)
   2772  1.1  mrg     return true;
   2773  1.1  mrg 
   2774  1.1  mrg   /* The frame also needs to be established in some special cases.  */
   2775  1.1  mrg   if (visium_frame_needed)
   2776  1.1  mrg     return true;
   2777  1.1  mrg 
   2778  1.1  mrg   return false;
   2779  1.1  mrg }
   2780  1.1  mrg 
   2781  1.1  mrg /* Profiling support.  Just a call to MCOUNT is needed.  No labelled counter
   2782  1.1  mrg    location is involved.  Proper support for __builtin_return_address is also
   2783  1.1  mrg    required, which is fairly straightforward provided a frame gets created.  */
   2784  1.1  mrg 
   2785  1.1  mrg void
   2786  1.1  mrg visium_profile_hook (void)
   2787  1.1  mrg {
   2788  1.1  mrg   visium_frame_needed = true;
   2789  1.1  mrg   emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "mcount"), LCT_NORMAL,
   2790  1.1  mrg 		     VOIDmode);
   2791  1.1  mrg }
   2792  1.1  mrg 
   2793  1.1  mrg /* A C expression whose value is RTL representing the address in a stack frame
   2794  1.1  mrg    where the pointer to the caller's frame is stored.  Assume that FRAMEADDR is
   2795  1.1  mrg    an RTL expression for the address of the stack frame itself.
   2796  1.1  mrg 
   2797  1.1  mrg    If you don't define this macro, the default is to return the value of
   2798  1.1  mrg    FRAMEADDR--that is, the stack frame address is also the address of the stack
   2799  1.1  mrg    word that points to the previous frame.  */
   2800  1.1  mrg 
   2801  1.1  mrg rtx
   2802  1.1  mrg visium_dynamic_chain_address (rtx frame)
   2803  1.1  mrg {
   2804  1.1  mrg   /* This is the default, but we need to make sure the frame gets created.  */
   2805  1.1  mrg   visium_frame_needed = true;
   2806  1.1  mrg   return frame;
   2807  1.1  mrg }
   2808  1.1  mrg 
   2809  1.1  mrg /* A C expression whose value is RTL representing the value of the return
   2810  1.1  mrg    address for the frame COUNT steps up from the current frame, after the
   2811  1.1  mrg    prologue.  FRAMEADDR is the frame pointer of the COUNT frame, or the frame
   2812  1.1  mrg    pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' is
   2813  1.1  mrg    defined.
   2814  1.1  mrg 
   2815  1.1  mrg    The value of the expression must always be the correct address when COUNT is
   2816  1.1  mrg    zero, but may be `NULL_RTX' if there is not way to determine the return
   2817  1.1  mrg    address of other frames.  */
   2818  1.1  mrg 
   2819  1.1  mrg rtx
   2820  1.1  mrg visium_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED)
   2821  1.1  mrg {
   2822  1.1  mrg   /* Dont try to compute anything other than frame zero.  */
   2823  1.1  mrg   if (count != 0)
   2824  1.1  mrg     return NULL_RTX;
   2825  1.1  mrg 
   2826  1.1  mrg   visium_frame_needed = true;
   2827  1.1  mrg   return
   2828  1.1  mrg     gen_frame_mem (Pmode, plus_constant (Pmode, hard_frame_pointer_rtx, 4));
   2829  1.1  mrg }
   2830  1.1  mrg 
   2831  1.1  mrg /* Helper function for EH_RETURN_HANDLER_RTX.  Return the RTX representing a
   2832  1.1  mrg    location in which to store the address of an exception handler to which we
   2833  1.1  mrg    should return.  */
   2834  1.1  mrg 
   2835  1.1  mrg rtx
   2836  1.1  mrg visium_eh_return_handler_rtx (void)
   2837  1.1  mrg {
   2838  1.1  mrg   rtx mem
   2839  1.1  mrg     = gen_frame_mem (SImode, plus_constant (Pmode, hard_frame_pointer_rtx, 4));
   2840  1.1  mrg   MEM_VOLATILE_P (mem) = 1;
   2841  1.1  mrg   return mem;
   2842  1.1  mrg }
   2843  1.1  mrg 
   2844  1.1  mrg static struct machine_function *
   2845  1.1  mrg visium_init_machine_status (void)
   2846  1.1  mrg {
   2847  1.1  mrg   return ggc_cleared_alloc<machine_function> ();
   2848  1.1  mrg }
   2849  1.1  mrg 
   2850  1.1  mrg /* The per-function data machinery is needed to indicate when a frame
   2851  1.1  mrg    is required. */
   2852  1.1  mrg 
   2853  1.1  mrg void
   2854  1.1  mrg visium_init_expanders (void)
   2855  1.1  mrg {
   2856  1.1  mrg   init_machine_status = visium_init_machine_status;
   2857  1.1  mrg }
   2858  1.1  mrg 
   2859  1.1  mrg /* Given a comparison code (EQ, NE, etc.) and the operands of a COMPARE,
   2860  1.1  mrg    return the mode to be used for the comparison.  */
   2861  1.1  mrg 
   2862  1.1  mrg machine_mode
   2863  1.1  mrg visium_select_cc_mode (enum rtx_code code, rtx op0, rtx op1)
   2864  1.1  mrg {
   2865  1.1  mrg   if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
   2866  1.1  mrg     {
   2867  1.1  mrg       switch (code)
   2868  1.1  mrg 	{
   2869  1.1  mrg 	case EQ:
   2870  1.1  mrg 	case NE:
   2871  1.1  mrg 	case ORDERED:
   2872  1.1  mrg 	case UNORDERED:
   2873  1.1  mrg 	case UNLT:
   2874  1.1  mrg 	case UNLE:
   2875  1.1  mrg 	case UNGT:
   2876  1.1  mrg 	case UNGE:
   2877  1.1  mrg 	  return CCFPmode;
   2878  1.1  mrg 
   2879  1.1  mrg 	case LT:
   2880  1.1  mrg 	case LE:
   2881  1.1  mrg 	case GT:
   2882  1.1  mrg 	case GE:
   2883  1.1  mrg 	  return CCFPEmode;
   2884  1.1  mrg 
   2885  1.1  mrg 	/* These 2 comparison codes are not supported.  */
   2886  1.1  mrg 	case UNEQ:
   2887  1.1  mrg 	case LTGT:
   2888  1.1  mrg 	default:
   2889  1.1  mrg 	  gcc_unreachable ();
   2890  1.1  mrg 	}
   2891  1.1  mrg     }
   2892  1.1  mrg 
   2893  1.1  mrg   /* This is for the cmp<mode>_sne pattern.  */
   2894  1.1  mrg   if (op1 == constm1_rtx)
   2895  1.1  mrg     return CCCmode;
   2896  1.1  mrg 
   2897  1.1  mrg   /* This is for the add<mode>3_insn_set_carry pattern.  */
   2898  1.1  mrg   if ((code == LTU || code == GEU)
   2899  1.1  mrg       && GET_CODE (op0) == PLUS
   2900  1.1  mrg       && rtx_equal_p (XEXP (op0, 0), op1))
   2901  1.1  mrg     return CCCmode;
   2902  1.1  mrg 
   2903  1.1  mrg   /* This is for the {add,sub,neg}<mode>3_insn_set_overflow pattern.  */
   2904  1.1  mrg   if ((code == EQ || code == NE)
   2905  1.1  mrg       && GET_CODE (op1) == UNSPEC
   2906  1.1  mrg       && (XINT (op1, 1) == UNSPEC_ADDV
   2907  1.1  mrg 	  || XINT (op1, 1) == UNSPEC_SUBV
   2908  1.1  mrg 	  || XINT (op1, 1) == UNSPEC_NEGV))
   2909  1.1  mrg     return CCVmode;
   2910  1.1  mrg 
   2911  1.1  mrg   if (op1 != const0_rtx)
   2912  1.1  mrg     return CCmode;
   2913  1.1  mrg 
   2914  1.1  mrg   switch (GET_CODE (op0))
   2915  1.1  mrg     {
   2916  1.1  mrg     case PLUS:
   2917  1.1  mrg     case MINUS:
   2918  1.1  mrg     case NEG:
   2919  1.1  mrg     case ASHIFT:
   2920  1.1  mrg     case LTU:
   2921  1.1  mrg     case LT:
   2922  1.1  mrg       /* The C and V flags may be set differently from a COMPARE with zero.
   2923  1.1  mrg 	 The consequence is that a comparison operator testing C or V must
   2924  1.1  mrg 	 be turned into another operator not testing C or V and yielding
   2925  1.1  mrg 	 the same result for a comparison with zero.  That's possible for
   2926  1.1  mrg 	 GE/LT which become NC/NS respectively, but not for GT/LE for which
   2927  1.1  mrg 	 the altered operator doesn't exist on the Visium.  */
   2928  1.1  mrg       return CCNZmode;
   2929  1.1  mrg 
   2930  1.1  mrg     case ZERO_EXTRACT:
   2931  1.1  mrg       /* This is a btst, the result is in C instead of Z.  */
   2932  1.1  mrg       return CCCmode;
   2933  1.1  mrg 
   2934  1.1  mrg     case REG:
   2935  1.1  mrg     case AND:
   2936  1.1  mrg     case IOR:
   2937  1.1  mrg     case XOR:
   2938  1.1  mrg     case NOT:
   2939  1.1  mrg     case ASHIFTRT:
   2940  1.1  mrg     case LSHIFTRT:
   2941  1.1  mrg     case TRUNCATE:
   2942  1.1  mrg     case SIGN_EXTEND:
   2943  1.1  mrg       /* Pretend that the flags are set as for a COMPARE with zero.
   2944  1.1  mrg 	 That's mostly true, except for the 2 right shift insns that
   2945  1.1  mrg 	 will set the C flag.  But the C flag is relevant only for
   2946  1.1  mrg 	 the unsigned comparison operators and they are eliminated
   2947  1.1  mrg 	 when applied to a comparison with zero.  */
   2948  1.1  mrg       return CCmode;
   2949  1.1  mrg 
   2950  1.1  mrg     /* ??? Cater to the junk RTXes sent by try_merge_compare.  */
   2951  1.1  mrg     case ASM_OPERANDS:
   2952  1.1  mrg     case CALL:
   2953  1.1  mrg     case CONST_INT:
   2954  1.1  mrg     case LO_SUM:
   2955  1.1  mrg     case HIGH:
   2956  1.1  mrg     case MEM:
   2957  1.1  mrg     case UNSPEC:
   2958  1.1  mrg     case ZERO_EXTEND:
   2959  1.1  mrg       return CCmode;
   2960  1.1  mrg 
   2961  1.1  mrg     default:
   2962  1.1  mrg       gcc_unreachable ();
   2963  1.1  mrg     }
   2964  1.1  mrg }
   2965  1.1  mrg 
   2966  1.1  mrg /* Split a compare-and-branch with CODE, operands OP0 and OP1, and LABEL.  */
   2967  1.1  mrg 
   2968  1.1  mrg void
   2969  1.1  mrg visium_split_cbranch (enum rtx_code code, rtx op0, rtx op1, rtx label)
   2970  1.1  mrg {
   2971  1.1  mrg   machine_mode cc_mode = visium_select_cc_mode (code, op0, op1);
   2972  1.1  mrg   rtx flags = gen_rtx_REG (cc_mode, FLAGS_REGNUM);
   2973  1.1  mrg 
   2974  1.1  mrg   rtx x = gen_rtx_COMPARE (cc_mode, op0, op1);
   2975  1.1  mrg   x = gen_rtx_SET (flags, x);
   2976  1.1  mrg   emit_insn (x);
   2977  1.1  mrg 
   2978  1.1  mrg   x = gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
   2979  1.1  mrg   x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, gen_rtx_LABEL_REF (Pmode, label),
   2980  1.1  mrg 			    pc_rtx);
   2981  1.1  mrg   x = gen_rtx_SET (pc_rtx, x);
   2982  1.1  mrg   emit_jump_insn (x);
   2983  1.1  mrg 
   2984  1.1  mrg   visium_flags_exposed = true;
   2985  1.1  mrg }
   2986  1.1  mrg 
   2987  1.1  mrg /* Branch instructions on the Visium.
   2988  1.1  mrg 
   2989  1.1  mrg    Setting aside the interrupt-handling specific instructions, the ISA has
   2990  1.1  mrg    two branch instructions: BRR and BRA.  The former is used to implement
   2991  1.1  mrg    short branches (+/- 2^17) within functions and its target is encoded in
   2992  1.1  mrg    the instruction.  The latter is used to implement all the other types
   2993  1.1  mrg    of control flow changes and its target might not be statically known
   2994  1.1  mrg    or even easily predictable at run time.  Here's a complete summary of
   2995  1.1  mrg    the patterns that generate a BRA instruction:
   2996  1.1  mrg 
   2997  1.1  mrg      1. Indirect jump
   2998  1.1  mrg      2. Table jump
   2999  1.1  mrg      3. Call
   3000  1.1  mrg      4. Sibling call
   3001  1.1  mrg      5. Return
   3002  1.1  mrg      6. Long branch
   3003  1.1  mrg      7. Trampoline
   3004  1.1  mrg 
   3005  1.1  mrg    Among these patterns, only the return (5) and the long branch (6) can be
   3006  1.1  mrg    conditional; all the other patterns are always unconditional.
   3007  1.1  mrg 
   3008  1.1  mrg    The following algorithm can be used to identify the pattern for which
   3009  1.1  mrg    the BRA instruction was generated and work out its target:
   3010  1.1  mrg 
   3011  1.1  mrg      A. If the source is r21 and the destination is r0, this is a return (5)
   3012  1.1  mrg 	and the target is the caller (i.e. the value of r21 on function's
   3013  1.1  mrg 	entry).
   3014  1.1  mrg 
   3015  1.1  mrg      B. If the source is rN, N != 21 and the destination is r0, this is either
   3016  1.1  mrg 	an indirect jump or a table jump (1, 2) and the target is not easily
   3017  1.1  mrg 	predictable.
   3018  1.1  mrg 
   3019  1.1  mrg      C. If the source is rN, N != 21 and the destination is r21, this is a call
   3020  1.1  mrg 	(3) and the target is given by the preceding MOVIL/MOVIU pair for rN,
   3021  1.1  mrg 	unless this is an indirect call in which case the target is not easily
   3022  1.1  mrg 	predictable.
   3023  1.1  mrg 
   3024  1.1  mrg      D. If the source is rN, N != 21 and the destination is also rN, this is
   3025  1.1  mrg 	either a sibling call or a trampoline (4, 7) and the target is given
   3026  1.1  mrg 	by the preceding MOVIL/MOVIU pair for rN.
   3027  1.1  mrg 
   3028  1.1  mrg      E. If the source is r21 and the destination is also r21, this is a long
   3029  1.1  mrg 	branch (6) and the target is given by the preceding MOVIL/MOVIU pair
   3030  1.1  mrg 	for r21.
   3031  1.1  mrg 
   3032  1.1  mrg    The other combinations are not used.  This implementation has been devised
   3033  1.1  mrg    to accommodate the branch predictor of the GR6 but is used unconditionally
   3034  1.1  mrg    by the compiler, i.e. including for earlier processors.  */
   3035  1.1  mrg 
   3036  1.1  mrg /* Output a conditional/unconditional branch to LABEL.  COND is the string
   3037  1.1  mrg    condition.  INSN is the instruction.  */
   3038  1.1  mrg 
   3039  1.1  mrg static const char *
   3040  1.1  mrg output_branch (rtx label, const char *cond, rtx_insn *insn)
   3041  1.1  mrg {
   3042  1.1  mrg   char str[64];
   3043  1.1  mrg   rtx operands[2];
   3044  1.1  mrg 
   3045  1.1  mrg   gcc_assert (cond);
   3046  1.1  mrg   operands[0] = label;
   3047  1.1  mrg 
   3048  1.1  mrg   /* If the length of the instruction is greater than 12, then this is a
   3049  1.1  mrg      long branch and we need to work harder to emit it properly.  */
   3050  1.1  mrg   if (get_attr_length (insn) > 12)
   3051  1.1  mrg     {
   3052  1.1  mrg       bool spilled;
   3053  1.1  mrg 
   3054  1.1  mrg       /* If the link register has been saved, then we use it.  */
   3055  1.1  mrg       if (current_function_saves_lr ())
   3056  1.1  mrg 	{
   3057  1.1  mrg 	  operands[1] = regno_reg_rtx [LINK_REGNUM];
   3058  1.1  mrg 	  spilled = false;
   3059  1.1  mrg 	}
   3060  1.1  mrg 
   3061  1.1  mrg       /* Or else, if the long-branch register isn't live, we use it.  */
   3062  1.1  mrg       else if (!df_regs_ever_live_p (long_branch_regnum))
   3063  1.1  mrg 	{
   3064  1.1  mrg 	  operands[1] = regno_reg_rtx [long_branch_regnum];
   3065  1.1  mrg 	  spilled = false;
   3066  1.1  mrg 	}
   3067  1.1  mrg 
   3068  1.1  mrg       /* Otherwise, we will use the long-branch register but we need to
   3069  1.1  mrg 	 spill it to the stack and reload it at the end.  We should have
   3070  1.1  mrg 	 reserved the LR slot for this purpose.  */
   3071  1.1  mrg       else
   3072  1.1  mrg 	{
   3073  1.1  mrg 	  operands[1] = regno_reg_rtx [long_branch_regnum];
   3074  1.1  mrg 	  spilled = true;
   3075  1.1  mrg 	  gcc_assert (current_function_has_lr_slot ());
   3076  1.1  mrg 	}
   3077  1.1  mrg 
   3078  1.1  mrg       /* First emit the spill to the stack:
   3079  1.1  mrg 
   3080  1.1  mrg 	   insn_in_delay_slot
   3081  1.1  mrg 	   write.l [1](sp),reg  */
   3082  1.1  mrg       if (spilled)
   3083  1.1  mrg 	{
   3084  1.1  mrg 	  if (final_sequence)
   3085  1.1  mrg 	    {
   3086  1.1  mrg 	      rtx_insn *delay = NEXT_INSN (insn);
   3087  1.1  mrg 	      gcc_assert (delay);
   3088  1.1  mrg 
   3089  1.1  mrg 	      final_scan_insn (delay, asm_out_file, optimize, 0, NULL);
   3090  1.1  mrg 	      PATTERN (delay) = gen_blockage ();
   3091  1.1  mrg 	      INSN_CODE (delay) = -1;
   3092  1.1  mrg 	    }
   3093  1.1  mrg 
   3094  1.1  mrg 	  if (current_function_saves_fp ())
   3095  1.1  mrg 	    output_asm_insn ("write.l 1(sp),%1", operands);
   3096  1.1  mrg 	  else
   3097  1.1  mrg 	    output_asm_insn ("write.l (sp),%1", operands);
   3098  1.1  mrg 	}
   3099  1.1  mrg 
   3100  1.1  mrg       /* Then emit the core sequence:
   3101  1.1  mrg 
   3102  1.1  mrg 	   moviu   reg,%u label
   3103  1.1  mrg 	   movil   reg,%l label
   3104  1.1  mrg 	   bra     tr,reg,reg
   3105  1.1  mrg 
   3106  1.1  mrg 	 We don't use r0 as the destination register of the branch because we
   3107  1.1  mrg 	 want the Branch Pre-decode Logic of the GR6 to use the Address Load
   3108  1.1  mrg 	 Array to predict the branch target.  */
   3109  1.1  mrg       output_asm_insn ("moviu   %1,%%u %0", operands);
   3110  1.1  mrg       output_asm_insn ("movil   %1,%%l %0", operands);
   3111  1.1  mrg       strcpy (str, "bra     ");
   3112  1.1  mrg       strcat (str, cond);
   3113  1.1  mrg       strcat (str, ",%1,%1");
   3114  1.1  mrg       if (!spilled)
   3115  1.1  mrg 	strcat (str, "%#");
   3116  1.1  mrg       strcat (str, "\t\t;long branch");
   3117  1.1  mrg       output_asm_insn (str, operands);
   3118  1.1  mrg 
   3119  1.1  mrg       /* Finally emit the reload:
   3120  1.1  mrg 
   3121  1.1  mrg 	    read.l reg,[1](sp)  */
   3122  1.1  mrg       if (spilled)
   3123  1.1  mrg 	{
   3124  1.1  mrg 	  if (current_function_saves_fp ())
   3125  1.1  mrg 	    output_asm_insn (" read.l %1,1(sp)", operands);
   3126  1.1  mrg 	  else
   3127  1.1  mrg 	    output_asm_insn (" read.l %1,(sp)", operands);
   3128  1.1  mrg 	}
   3129  1.1  mrg     }
   3130  1.1  mrg 
   3131  1.1  mrg   /* Or else, if the label is PC, then this is a return.  */
   3132  1.1  mrg   else if (label == pc_rtx)
   3133  1.1  mrg     {
   3134  1.1  mrg       strcpy (str, "bra     ");
   3135  1.1  mrg       strcat (str, cond);
   3136  1.1  mrg       strcat (str, ",r21,r0%#\t\t;return");
   3137  1.1  mrg       output_asm_insn (str, operands);
   3138  1.1  mrg     }
   3139  1.1  mrg 
   3140  1.1  mrg   /* Otherwise, this is a short branch.  */
   3141  1.1  mrg   else
   3142  1.1  mrg     {
   3143  1.1  mrg       strcpy (str, "brr     ");
   3144  1.1  mrg       strcat (str, cond);
   3145  1.1  mrg       strcat (str, ",%0%#");
   3146  1.1  mrg       output_asm_insn (str, operands);
   3147  1.1  mrg     }
   3148  1.1  mrg 
   3149  1.1  mrg   return "";
   3150  1.1  mrg }
   3151  1.1  mrg 
   3152  1.1  mrg /* Output an unconditional branch to LABEL.  INSN is the instruction.  */
   3153  1.1  mrg 
   3154  1.1  mrg const char *
   3155  1.1  mrg output_ubranch (rtx label, rtx_insn *insn)
   3156  1.1  mrg {
   3157  1.1  mrg   return output_branch (label, "tr", insn);
   3158  1.1  mrg }
   3159  1.1  mrg 
   3160  1.1  mrg /* Output a conditional branch to LABEL.  CODE is the comparison code.
   3161  1.1  mrg    CC_MODE is the mode of the CC register.  REVERSED is non-zero if we
   3162  1.1  mrg    should reverse the sense of the comparison.  INSN is the instruction.  */
   3163  1.1  mrg 
   3164  1.1  mrg const char *
   3165  1.1  mrg output_cbranch (rtx label, enum rtx_code code, machine_mode cc_mode,
   3166  1.1  mrg 		int reversed, rtx_insn *insn)
   3167  1.1  mrg {
   3168  1.1  mrg   const char *cond;
   3169  1.1  mrg 
   3170  1.1  mrg   if (reversed)
   3171  1.1  mrg     {
   3172  1.1  mrg       if (cc_mode == CCFPmode || cc_mode == CCFPEmode)
   3173  1.1  mrg 	code = reverse_condition_maybe_unordered (code);
   3174  1.1  mrg       else
   3175  1.1  mrg 	code = reverse_condition (code);
   3176  1.1  mrg     }
   3177  1.1  mrg 
   3178  1.1  mrg   switch (code)
   3179  1.1  mrg     {
   3180  1.1  mrg     case NE:
   3181  1.1  mrg       if (cc_mode == CCCmode)
   3182  1.1  mrg 	cond = "cs";
   3183  1.1  mrg       else if (cc_mode == CCVmode)
   3184  1.1  mrg 	cond = "os";
   3185  1.1  mrg       else
   3186  1.1  mrg 	cond = "ne";
   3187  1.1  mrg       break;
   3188  1.1  mrg 
   3189  1.1  mrg     case EQ:
   3190  1.1  mrg       if (cc_mode == CCCmode)
   3191  1.1  mrg 	cond = "cc";
   3192  1.1  mrg       else if (cc_mode == CCVmode)
   3193  1.1  mrg 	cond = "oc";
   3194  1.1  mrg       else
   3195  1.1  mrg 	cond = "eq";
   3196  1.1  mrg       break;
   3197  1.1  mrg 
   3198  1.1  mrg     case GE:
   3199  1.1  mrg       if (cc_mode == CCNZmode)
   3200  1.1  mrg 	cond = "nc";
   3201  1.1  mrg       else
   3202  1.1  mrg 	cond = "ge";
   3203  1.1  mrg       break;
   3204  1.1  mrg 
   3205  1.1  mrg     case GT:
   3206  1.1  mrg       cond = "gt";
   3207  1.1  mrg       break;
   3208  1.1  mrg 
   3209  1.1  mrg     case LE:
   3210  1.1  mrg       if (cc_mode == CCFPmode || cc_mode == CCFPEmode)
   3211  1.1  mrg 	cond = "ls";
   3212  1.1  mrg       else
   3213  1.1  mrg 	cond = "le";
   3214  1.1  mrg       break;
   3215  1.1  mrg 
   3216  1.1  mrg     case LT:
   3217  1.1  mrg       if (cc_mode == CCFPmode || cc_mode == CCFPEmode)
   3218  1.1  mrg 	cond = "cs"; /* or "ns" */
   3219  1.1  mrg       else if (cc_mode == CCNZmode)
   3220  1.1  mrg 	cond = "ns";
   3221  1.1  mrg       else
   3222  1.1  mrg 	cond = "lt";
   3223  1.1  mrg       break;
   3224  1.1  mrg 
   3225  1.1  mrg     case GEU:
   3226  1.1  mrg       cond = "cc";
   3227  1.1  mrg       break;
   3228  1.1  mrg 
   3229  1.1  mrg     case GTU:
   3230  1.1  mrg       cond = "hi";
   3231  1.1  mrg       break;
   3232  1.1  mrg 
   3233  1.1  mrg     case LEU:
   3234  1.1  mrg       cond = "ls";
   3235  1.1  mrg       break;
   3236  1.1  mrg 
   3237  1.1  mrg     case LTU:
   3238  1.1  mrg       cond = "cs";
   3239  1.1  mrg       break;
   3240  1.1  mrg 
   3241  1.1  mrg     case UNORDERED:
   3242  1.1  mrg       cond = "os";
   3243  1.1  mrg       break;
   3244  1.1  mrg 
   3245  1.1  mrg     case ORDERED:
   3246  1.1  mrg       cond = "oc";
   3247  1.1  mrg       break;
   3248  1.1  mrg 
   3249  1.1  mrg     case UNGE:
   3250  1.1  mrg       cond = "cc"; /* or "nc" */
   3251  1.1  mrg       break;
   3252  1.1  mrg 
   3253  1.1  mrg     case UNGT:
   3254  1.1  mrg       cond = "hi";
   3255  1.1  mrg       break;
   3256  1.1  mrg 
   3257  1.1  mrg     case UNLE:
   3258  1.1  mrg       cond = "le";
   3259  1.1  mrg       break;
   3260  1.1  mrg 
   3261  1.1  mrg     case UNLT:
   3262  1.1  mrg       cond = "lt";
   3263  1.1  mrg       break;
   3264  1.1  mrg 
   3265  1.1  mrg     /* These 2 comparison codes are not supported.  */
   3266  1.1  mrg     case UNEQ:
   3267  1.1  mrg     case LTGT:
   3268  1.1  mrg     default:
   3269  1.1  mrg       gcc_unreachable ();
   3270  1.1  mrg     }
   3271  1.1  mrg 
   3272  1.1  mrg   return output_branch (label, cond, insn);
   3273  1.1  mrg }
   3274  1.1  mrg 
   3275  1.1  mrg /* Implement TARGET_PRINT_OPERAND_PUNCT_VALID_P.  */
   3276  1.1  mrg 
   3277  1.1  mrg static bool
   3278  1.1  mrg visium_print_operand_punct_valid_p (unsigned char code)
   3279  1.1  mrg {
   3280  1.1  mrg   return code == '#';
   3281  1.1  mrg }
   3282  1.1  mrg 
   3283  1.1  mrg /* Implement TARGET_PRINT_OPERAND.  Output to stdio stream FILE the assembler
   3284  1.1  mrg    syntax for an instruction operand OP subject to the modifier LETTER.  */
   3285  1.1  mrg 
   3286  1.1  mrg static void
   3287  1.1  mrg visium_print_operand (FILE *file, rtx op, int letter)
   3288  1.1  mrg {
   3289  1.1  mrg   switch (letter)
   3290  1.1  mrg     {
   3291  1.1  mrg     case '#':
   3292  1.1  mrg       /* Output an insn in a delay slot.  */
   3293  1.1  mrg       if (final_sequence)
   3294  1.1  mrg 	visium_indent_opcode = 1;
   3295  1.1  mrg       else
   3296  1.1  mrg 	fputs ("\n\t nop", file);
   3297  1.1  mrg       return;
   3298  1.1  mrg 
   3299  1.1  mrg     case 'b':
   3300  1.1  mrg       /* Print LS 8 bits of operand.  */
   3301  1.1  mrg       fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED, UINTVAL (op) & 0xff);
   3302  1.1  mrg       return;
   3303  1.1  mrg 
   3304  1.1  mrg     case 'w':
   3305  1.1  mrg       /* Print LS 16 bits of operand.  */
   3306  1.1  mrg       fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED, UINTVAL (op) & 0xffff);
   3307  1.1  mrg       return;
   3308  1.1  mrg 
   3309  1.1  mrg     case 'u':
   3310  1.1  mrg       /* Print MS 16 bits of operand.  */
   3311  1.1  mrg       fprintf (file,
   3312  1.1  mrg 	       HOST_WIDE_INT_PRINT_UNSIGNED, (UINTVAL (op) >> 16) & 0xffff);
   3313  1.1  mrg       return;
   3314  1.1  mrg 
   3315  1.1  mrg     case 'r':
   3316  1.1  mrg       /* It's either a register or zero.  */
   3317  1.1  mrg       if (GET_CODE (op) == REG)
   3318  1.1  mrg 	fputs (reg_names[REGNO (op)], file);
   3319  1.1  mrg       else
   3320  1.1  mrg 	fputs (reg_names[0], file);
   3321  1.1  mrg       return;
   3322  1.1  mrg 
   3323  1.1  mrg     case 'f':
   3324  1.1  mrg       /* It's either a FP register or zero.  */
   3325  1.1  mrg        if (GET_CODE (op) == REG)
   3326  1.1  mrg 	fputs (reg_names[REGNO (op)], file);
   3327  1.1  mrg        else
   3328  1.1  mrg 	fputs (reg_names[FP_FIRST_REGNUM], file);
   3329  1.1  mrg        return;
   3330  1.1  mrg     }
   3331  1.1  mrg 
   3332  1.1  mrg   switch (GET_CODE (op))
   3333  1.1  mrg     {
   3334  1.1  mrg     case REG:
   3335  1.1  mrg       if (letter == 'd')
   3336  1.1  mrg 	fputs (reg_names[REGNO (op) + 1], file);
   3337  1.1  mrg       else
   3338  1.1  mrg 	fputs (reg_names[REGNO (op)], file);
   3339  1.1  mrg       break;
   3340  1.1  mrg 
   3341  1.1  mrg     case SYMBOL_REF:
   3342  1.1  mrg     case LABEL_REF:
   3343  1.1  mrg     case CONST:
   3344  1.1  mrg       output_addr_const (file, op);
   3345  1.1  mrg       break;
   3346  1.1  mrg 
   3347  1.1  mrg     case MEM:
   3348  1.1  mrg       visium_print_operand_address (file, GET_MODE (op), XEXP (op, 0));
   3349  1.1  mrg       break;
   3350  1.1  mrg 
   3351  1.1  mrg     case CONST_INT:
   3352  1.1  mrg       fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op));
   3353  1.1  mrg       break;
   3354  1.1  mrg 
   3355  1.1  mrg     case CODE_LABEL:
   3356  1.1  mrg       asm_fprintf (file, "%LL%d", CODE_LABEL_NUMBER (op));
   3357  1.1  mrg       break;
   3358  1.1  mrg 
   3359  1.1  mrg     case HIGH:
   3360  1.1  mrg       visium_print_operand (file, XEXP (op, 1), letter);
   3361  1.1  mrg       break;
   3362  1.1  mrg 
   3363  1.1  mrg     default:
   3364  1.1  mrg       fatal_insn ("illegal operand ", op);
   3365  1.1  mrg     }
   3366  1.1  mrg }
   3367  1.1  mrg 
   3368  1.1  mrg /* Implement TARGET_PRINT_OPERAND_ADDRESS.  Output to stdio stream FILE the
   3369  1.1  mrg    assembler syntax for an instruction operand that is a memory reference
   3370  1.1  mrg    whose address is ADDR.  */
   3371  1.1  mrg 
   3372  1.1  mrg static void
   3373  1.1  mrg visium_print_operand_address (FILE *file, machine_mode mode, rtx addr)
   3374  1.1  mrg {
   3375  1.1  mrg   switch (GET_CODE (addr))
   3376  1.1  mrg     {
   3377  1.1  mrg     case REG:
   3378  1.1  mrg     case SUBREG:
   3379  1.1  mrg       fprintf (file, "(%s)", reg_names[true_regnum (addr)]);
   3380  1.1  mrg       break;
   3381  1.1  mrg 
   3382  1.1  mrg     case PLUS:
   3383  1.1  mrg       {
   3384  1.1  mrg 	rtx x = XEXP (addr, 0), y = XEXP (addr, 1);
   3385  1.1  mrg 
   3386  1.1  mrg 	switch (GET_CODE (x))
   3387  1.1  mrg 	  {
   3388  1.1  mrg 	  case REG:
   3389  1.1  mrg 	  case SUBREG:
   3390  1.1  mrg 	    if (CONST_INT_P (y))
   3391  1.1  mrg 	      {
   3392  1.1  mrg 		unsigned int regno = true_regnum (x);
   3393  1.1  mrg 		HOST_WIDE_INT val = INTVAL (y);
   3394  1.1  mrg 		switch (mode)
   3395  1.1  mrg 		  {
   3396  1.1  mrg 		  case E_SImode:
   3397  1.1  mrg 		  case E_DImode:
   3398  1.1  mrg 		  case E_SFmode:
   3399  1.1  mrg 		  case E_DFmode:
   3400  1.1  mrg 		    val >>= 2;
   3401  1.1  mrg 		    break;
   3402  1.1  mrg 
   3403  1.1  mrg 		  case E_HImode:
   3404  1.1  mrg 		    val >>= 1;
   3405  1.1  mrg 		    break;
   3406  1.1  mrg 
   3407  1.1  mrg 		  case E_QImode:
   3408  1.1  mrg 		  default:
   3409  1.1  mrg 		    break;
   3410  1.1  mrg 		  }
   3411  1.1  mrg 	        fprintf (file, HOST_WIDE_INT_PRINT_DEC"(%s)", val,
   3412  1.1  mrg 			 reg_names[regno]);
   3413  1.1  mrg 	      }
   3414  1.1  mrg 	    else
   3415  1.1  mrg 	      fatal_insn ("illegal operand address (1)", addr);
   3416  1.1  mrg 	    break;
   3417  1.1  mrg 
   3418  1.1  mrg 	  default:
   3419  1.1  mrg 	    if (CONSTANT_P (x) && CONSTANT_P (y))
   3420  1.1  mrg 	      output_addr_const (file, addr);
   3421  1.1  mrg 	    else
   3422  1.1  mrg 	      fatal_insn ("illegal operand address (2)", addr);
   3423  1.1  mrg 	    break;
   3424  1.1  mrg 	  }
   3425  1.1  mrg       }
   3426  1.1  mrg       break;
   3427  1.1  mrg 
   3428  1.1  mrg     case LABEL_REF:
   3429  1.1  mrg     case SYMBOL_REF:
   3430  1.1  mrg     case CONST_INT:
   3431  1.1  mrg     case CONST:
   3432  1.1  mrg       output_addr_const (file, addr);
   3433  1.1  mrg       break;
   3434  1.1  mrg 
   3435  1.1  mrg     case NOTE:
   3436  1.1  mrg       if (NOTE_KIND (addr) != NOTE_INSN_DELETED_LABEL)
   3437  1.1  mrg 	fatal_insn ("illegal operand address (3)", addr);
   3438  1.1  mrg       break;
   3439  1.1  mrg 
   3440  1.1  mrg     case CODE_LABEL:
   3441  1.1  mrg       asm_fprintf (file, "%LL%d", CODE_LABEL_NUMBER (addr));
   3442  1.1  mrg       break;
   3443  1.1  mrg 
   3444  1.1  mrg     default:
   3445  1.1  mrg       fatal_insn ("illegal operand address (4)", addr);
   3446  1.1  mrg       break;
   3447  1.1  mrg     }
   3448  1.1  mrg }
   3449  1.1  mrg 
   3450  1.1  mrg /* The Visium stack frames look like:
   3451  1.1  mrg 
   3452  1.1  mrg               Before call                      After call
   3453  1.1  mrg         +-----------------------+       +-----------------------+
   3454  1.1  mrg         |                       |       |                       |
   3455  1.1  mrg    high |      previous         |       |      previous         |
   3456  1.1  mrg    mem  |      frame            |       |      frame            |
   3457  1.1  mrg         |                       |       |                       |
   3458  1.1  mrg         +-----------------------+       +-----------------------+
   3459  1.1  mrg         |                       |       |                       |
   3460  1.1  mrg         |  arguments on stack   |       |  arguments on stack   |
   3461  1.1  mrg         |                       |       |                       |
   3462  1.1  mrg   SP+0->+-----------------------+       +-----------------------+
   3463  1.1  mrg                                         |  reg parm save area,  |
   3464  1.1  mrg                                         |  only created for     |
   3465  1.1  mrg                                         |  variable argument    |
   3466  1.1  mrg                                         |  functions            |
   3467  1.1  mrg                                         +-----------------------+
   3468  1.1  mrg                                         |                       |
   3469  1.1  mrg                                         |  register save area   |
   3470  1.1  mrg                                         |                       |
   3471  1.1  mrg                                         +-----------------------+
   3472  1.1  mrg                                         |                       |
   3473  1.1  mrg                                         |  local variables      |
   3474  1.1  mrg                                         |                       |
   3475  1.1  mrg                                   FP+8->+-----------------------+
   3476  1.1  mrg                                         |    return address     |
   3477  1.1  mrg                                   FP+4->+-----------------------+
   3478  1.1  mrg                                         |      previous FP      |
   3479  1.1  mrg                                   FP+0->+-----------------------+
   3480  1.1  mrg                                         |                       |
   3481  1.1  mrg                                         |  alloca allocations   |
   3482  1.1  mrg                                         |                       |
   3483  1.1  mrg                                         +-----------------------+
   3484  1.1  mrg                                         |                       |
   3485  1.1  mrg    low                                  |  arguments on stack   |
   3486  1.1  mrg    mem                                  |                       |
   3487  1.1  mrg                                   SP+0->+-----------------------+
   3488  1.1  mrg 
   3489  1.1  mrg    Notes:
   3490  1.1  mrg    1) The "reg parm save area" does not exist for non variable argument fns.
   3491  1.1  mrg    2) The FP register is not saved if `frame_pointer_needed' is zero and it
   3492  1.1  mrg       is not altered in the current function.
   3493  1.1  mrg    3) The return address is not saved if there is no frame pointer and the
   3494  1.1  mrg       current function is leaf.
   3495  1.1  mrg    4) If the return address is not saved and the static chain register is
   3496  1.1  mrg       live in the function, we allocate the return address slot to be able
   3497  1.1  mrg       to spill the register for a long branch.  */
   3498  1.1  mrg 
   3499  1.1  mrg /* Define the register classes for local purposes.  */
   3500  1.1  mrg enum reg_type { general, mdb, mdc, floating, last_type};
   3501  1.1  mrg 
   3502  1.1  mrg #define GET_REG_TYPE(regno)          \
   3503  1.1  mrg   (GP_REGISTER_P (regno) ? general : \
   3504  1.1  mrg    (regno) == MDB_REGNUM ? mdb :      \
   3505  1.1  mrg    (regno) == MDC_REGNUM ? mdc :      \
   3506  1.1  mrg    floating)
   3507  1.1  mrg 
   3508  1.1  mrg /* First regno of each register type.  */
   3509  1.1  mrg const int first_regno[last_type] = {0, MDB_REGNUM, MDC_REGNUM, FP_FIRST_REGNUM};
   3510  1.1  mrg 
   3511  1.1  mrg /* Size in bytes of each register type.  */
   3512  1.1  mrg const int reg_type_size[last_type] = {4, 8, 4, 4};
   3513  1.1  mrg 
   3514  1.1  mrg /* Structure to be filled in by visium_compute_frame_size.  */
   3515  1.1  mrg struct visium_frame_info
   3516  1.1  mrg {
   3517  1.1  mrg   unsigned int save_area_size;	/* # bytes in the reg parm save area.  */
   3518  1.1  mrg   unsigned int reg_size1;	/* # bytes to store first block of regs.  */
   3519  1.1  mrg   unsigned int reg_size2;	/* # bytes to store second block of regs.  */
   3520  1.1  mrg   unsigned int max_reg1;	/* max. regno in first block */
   3521  1.1  mrg   unsigned int var_size;	/* # bytes that variables take up.  */
   3522  1.1  mrg   unsigned int save_fp;		/* Nonzero if fp must be saved.  */
   3523  1.1  mrg   unsigned int save_lr;		/* Nonzero if lr must be saved.  */
   3524  1.1  mrg   unsigned int lr_slot;		/* Nonzero if the lr slot is needed.  */
   3525  1.1  mrg   unsigned int combine;		/* Nonzero if we can combine the allocation of
   3526  1.1  mrg 				   variables and regs. */
   3527  1.1  mrg   unsigned int interrupt;	/* Nonzero if the function is an interrupt
   3528  1.1  mrg 				   handler. */
   3529  1.1  mrg   unsigned int mask[last_type];	/* Masks of saved regs: gp, mdb, mdc, fp */
   3530  1.1  mrg };
   3531  1.1  mrg 
   3532  1.1  mrg /* Current frame information calculated by visium_compute_frame_size.  */
   3533  1.1  mrg static struct visium_frame_info current_frame_info;
   3534  1.1  mrg 
   3535  1.1  mrg /* Accessor for current_frame_info.save_fp.  */
   3536  1.1  mrg 
   3537  1.1  mrg static inline bool
   3538  1.1  mrg current_function_saves_fp (void)
   3539  1.1  mrg {
   3540  1.1  mrg   return current_frame_info.save_fp != 0;
   3541  1.1  mrg }
   3542  1.1  mrg 
   3543  1.1  mrg /* Accessor for current_frame_info.save_lr.  */
   3544  1.1  mrg 
   3545  1.1  mrg static inline bool
   3546  1.1  mrg current_function_saves_lr (void)
   3547  1.1  mrg {
   3548  1.1  mrg   return current_frame_info.save_lr != 0;
   3549  1.1  mrg }
   3550  1.1  mrg 
   3551  1.1  mrg /* Accessor for current_frame_info.lr_slot.  */
   3552  1.1  mrg 
   3553  1.1  mrg static inline bool
   3554  1.1  mrg current_function_has_lr_slot (void)
   3555  1.1  mrg {
   3556  1.1  mrg   return current_frame_info.lr_slot != 0;
   3557  1.1  mrg }
   3558  1.1  mrg 
   3559  1.1  mrg /* Return non-zero if register REGNO needs to be saved in the frame.  */
   3560  1.1  mrg 
   3561  1.1  mrg static int
   3562  1.1  mrg visium_save_reg_p (int interrupt, int regno)
   3563  1.1  mrg {
   3564  1.1  mrg   switch (regno)
   3565  1.1  mrg     {
   3566  1.1  mrg     case HARD_FRAME_POINTER_REGNUM:
   3567  1.1  mrg       /* This register is call-saved but handled specially.  */
   3568  1.1  mrg       return 0;
   3569  1.1  mrg 
   3570  1.1  mrg     case MDC_REGNUM:
   3571  1.1  mrg       /* This register is fixed but can be modified.  */
   3572  1.1  mrg       break;
   3573  1.1  mrg 
   3574  1.1  mrg     case 29:
   3575  1.1  mrg     case 30:
   3576  1.1  mrg       /* These registers are fixed and hold the interrupt context.  */
   3577  1.1  mrg       return (interrupt != 0);
   3578  1.1  mrg 
   3579  1.1  mrg     default:
   3580  1.1  mrg       /* The other fixed registers are either immutable or special.  */
   3581  1.1  mrg       if (fixed_regs[regno])
   3582  1.1  mrg 	return 0;
   3583  1.1  mrg       break;
   3584  1.1  mrg     }
   3585  1.1  mrg 
   3586  1.1  mrg   if (interrupt)
   3587  1.1  mrg     {
   3588  1.1  mrg       if (crtl->is_leaf)
   3589  1.1  mrg 	{
   3590  1.1  mrg 	  if (df_regs_ever_live_p (regno))
   3591  1.1  mrg 	    return 1;
   3592  1.1  mrg 	}
   3593  1.1  mrg       else if (call_used_or_fixed_reg_p (regno))
   3594  1.1  mrg 	return 1;
   3595  1.1  mrg 
   3596  1.1  mrg       /* To save mdb requires two temporary registers.  To save mdc or
   3597  1.1  mrg          any of the floating registers requires one temporary
   3598  1.1  mrg          register.  If this is an interrupt routine, the temporary
   3599  1.1  mrg          registers need to be saved as well.  These temporary registers
   3600  1.1  mrg          are call used, so we only need deal with the case of leaf
   3601  1.1  mrg          functions here.  */
   3602  1.1  mrg       if (regno == PROLOGUE_TMP_REGNUM)
   3603  1.1  mrg 	{
   3604  1.1  mrg 	  if (df_regs_ever_live_p (MDB_REGNUM)
   3605  1.1  mrg 	      || df_regs_ever_live_p (MDC_REGNUM))
   3606  1.1  mrg 	    return 1;
   3607  1.1  mrg 
   3608  1.1  mrg 	  for (int i = FP_FIRST_REGNUM; i <= FP_LAST_REGNUM; i++)
   3609  1.1  mrg 	    if (df_regs_ever_live_p (i))
   3610  1.1  mrg 	      return 1;
   3611  1.1  mrg 	}
   3612  1.1  mrg 
   3613  1.1  mrg       else if (regno == PROLOGUE_TMP_REGNUM + 1)
   3614  1.1  mrg 	{
   3615  1.1  mrg 	  if (df_regs_ever_live_p (MDB_REGNUM))
   3616  1.1  mrg 	    return 1;
   3617  1.1  mrg 	}
   3618  1.1  mrg     }
   3619  1.1  mrg 
   3620  1.1  mrg   return df_regs_ever_live_p (regno) && !call_used_or_fixed_reg_p (regno);
   3621  1.1  mrg }
   3622  1.1  mrg 
   3623  1.1  mrg /* Compute the frame size required by the function.  This function is called
   3624  1.1  mrg    during the reload pass and also by visium_expand_prologue.  */
   3625  1.1  mrg 
   3626  1.1  mrg static int
   3627  1.1  mrg visium_compute_frame_size (int size)
   3628  1.1  mrg {
   3629  1.1  mrg   const int save_area_size = visium_reg_parm_save_area_size;
   3630  1.1  mrg   const int var_size = VISIUM_STACK_ALIGN (size);
   3631  1.1  mrg   const int save_fp
   3632  1.1  mrg     = frame_pointer_needed || df_regs_ever_live_p (HARD_FRAME_POINTER_REGNUM);
   3633  1.1  mrg   const int save_lr = frame_pointer_needed || !crtl->is_leaf;
   3634  1.1  mrg   const int lr_slot = !save_lr && df_regs_ever_live_p (long_branch_regnum);
   3635  1.1  mrg   const int local_frame_offset
   3636  1.1  mrg     = (save_fp + save_lr + lr_slot) * UNITS_PER_WORD;
   3637  1.1  mrg   const int interrupt = visium_interrupt_function_p ();
   3638  1.1  mrg   unsigned int mask[last_type];
   3639  1.1  mrg   int reg_size1 = 0;
   3640  1.1  mrg   int max_reg1 = 0;
   3641  1.1  mrg   int reg_size2 = 0;
   3642  1.1  mrg   int reg_size;
   3643  1.1  mrg   int combine;
   3644  1.1  mrg   int frame_size;
   3645  1.1  mrg   int regno;
   3646  1.1  mrg 
   3647  1.1  mrg   memset (mask, 0, last_type * sizeof (unsigned int));
   3648  1.1  mrg 
   3649  1.1  mrg   /* The registers may need stacking in 2 blocks since only 32 32-bit words
   3650  1.1  mrg      can be indexed from a given base address.  */
   3651  1.1  mrg   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
   3652  1.1  mrg     {
   3653  1.1  mrg       if (visium_save_reg_p (interrupt, regno))
   3654  1.1  mrg 	{
   3655  1.1  mrg 	  enum reg_type reg_type = GET_REG_TYPE (regno);
   3656  1.1  mrg 	  int mask_bit = 1 << (regno - first_regno[reg_type]);
   3657  1.1  mrg 	  int nbytes = reg_type_size[reg_type];
   3658  1.1  mrg 
   3659  1.1  mrg 	  if (reg_size1 + nbytes > 32 * UNITS_PER_WORD)
   3660  1.1  mrg 	    break;
   3661  1.1  mrg 
   3662  1.1  mrg 	  reg_size1 += nbytes;
   3663  1.1  mrg 	  max_reg1 = regno;
   3664  1.1  mrg 	  mask[reg_type] |= mask_bit;
   3665  1.1  mrg 	}
   3666  1.1  mrg     }
   3667  1.1  mrg 
   3668  1.1  mrg   for (regno = max_reg1 + 1; regno < FIRST_PSEUDO_REGISTER; regno++)
   3669  1.1  mrg     {
   3670  1.1  mrg       if (visium_save_reg_p (interrupt, regno))
   3671  1.1  mrg 	{
   3672  1.1  mrg 	  enum reg_type reg_type = GET_REG_TYPE (regno);
   3673  1.1  mrg 	  int mask_bit = 1 << (regno - first_regno[reg_type]);
   3674  1.1  mrg 	  int nbytes = reg_type_size[reg_type];
   3675  1.1  mrg 
   3676  1.1  mrg 	  reg_size2 += nbytes;
   3677  1.1  mrg 	  mask[reg_type] |= mask_bit;
   3678  1.1  mrg 	}
   3679  1.1  mrg     }
   3680  1.1  mrg 
   3681  1.1  mrg   reg_size = reg_size2 ? reg_size2 : reg_size1;
   3682  1.1  mrg   combine = (local_frame_offset + var_size + reg_size) <= 32 * UNITS_PER_WORD;
   3683  1.1  mrg   frame_size
   3684  1.1  mrg     = local_frame_offset + var_size + reg_size2 + reg_size1 + save_area_size;
   3685  1.1  mrg 
   3686  1.1  mrg   current_frame_info.save_area_size = save_area_size;
   3687  1.1  mrg   current_frame_info.reg_size1 = reg_size1;
   3688  1.1  mrg   current_frame_info.max_reg1 = max_reg1;
   3689  1.1  mrg   current_frame_info.reg_size2 = reg_size2;
   3690  1.1  mrg   current_frame_info.var_size = var_size;
   3691  1.1  mrg   current_frame_info.save_fp = save_fp;
   3692  1.1  mrg   current_frame_info.save_lr = save_lr;
   3693  1.1  mrg   current_frame_info.lr_slot = lr_slot;
   3694  1.1  mrg   current_frame_info.combine = combine;
   3695  1.1  mrg   current_frame_info.interrupt = interrupt;
   3696  1.1  mrg 
   3697  1.1  mrg   memcpy (current_frame_info.mask, mask, last_type * sizeof (unsigned int));
   3698  1.1  mrg 
   3699  1.1  mrg   return frame_size;
   3700  1.1  mrg }
   3701  1.1  mrg 
   3702  1.1  mrg /* Helper function for INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET).  Define
   3703  1.1  mrg    the offset between two registers, one to be eliminated, and the other its
   3704  1.1  mrg    replacement, at the start of a routine.  */
   3705  1.1  mrg 
   3706  1.1  mrg int
   3707  1.1  mrg visium_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED)
   3708  1.1  mrg {
   3709  1.1  mrg   const int save_fp = current_frame_info.save_fp;
   3710  1.1  mrg   const int save_lr = current_frame_info.save_lr;
   3711  1.1  mrg   const int lr_slot = current_frame_info.lr_slot;
   3712  1.1  mrg   int offset;
   3713  1.1  mrg 
   3714  1.1  mrg   if (from == FRAME_POINTER_REGNUM)
   3715  1.1  mrg     offset = (save_fp + save_lr + lr_slot) * UNITS_PER_WORD;
   3716  1.1  mrg   else if (from == ARG_POINTER_REGNUM)
   3717  1.1  mrg     offset = visium_compute_frame_size (get_frame_size ());
   3718  1.1  mrg   else
   3719  1.1  mrg     gcc_unreachable ();
   3720  1.1  mrg 
   3721  1.1  mrg   return offset;
   3722  1.1  mrg }
   3723  1.1  mrg 
   3724  1.1  mrg /* For an interrupt handler, we may be saving call-clobbered registers.
   3725  1.1  mrg    Say the epilogue uses these in addition to the link register.  */
   3726  1.1  mrg 
   3727  1.1  mrg int
   3728  1.1  mrg visium_epilogue_uses (int regno)
   3729  1.1  mrg {
   3730  1.1  mrg   if (regno == LINK_REGNUM)
   3731  1.1  mrg     return 1;
   3732  1.1  mrg 
   3733  1.1  mrg   if (reload_completed)
   3734  1.1  mrg     {
   3735  1.1  mrg       enum reg_type reg_type = GET_REG_TYPE (regno);
   3736  1.1  mrg       int mask_bit = 1 << (regno - first_regno[reg_type]);
   3737  1.1  mrg 
   3738  1.1  mrg       return (current_frame_info.mask[reg_type] & mask_bit) != 0;
   3739  1.1  mrg     }
   3740  1.1  mrg 
   3741  1.1  mrg   return 0;
   3742  1.1  mrg }
   3743  1.1  mrg 
   3744  1.1  mrg /* Wrapper around emit_insn that sets RTX_FRAME_RELATED_P on the insn.  */
   3745  1.1  mrg 
   3746  1.1  mrg static rtx
   3747  1.1  mrg emit_frame_insn (rtx x)
   3748  1.1  mrg {
   3749  1.1  mrg   x = emit_insn (x);
   3750  1.1  mrg   RTX_FRAME_RELATED_P (x) = 1;
   3751  1.1  mrg   return x;
   3752  1.1  mrg }
   3753  1.1  mrg 
   3754  1.1  mrg /* Allocate ALLOC bytes on the stack and save the registers LOW_REGNO to
   3755  1.1  mrg    HIGH_REGNO at OFFSET from the stack pointer.  */
   3756  1.1  mrg 
   3757  1.1  mrg static void
   3758  1.1  mrg visium_save_regs (int alloc, int offset, int low_regno, int high_regno)
   3759  1.1  mrg {
   3760  1.1  mrg   /* If this is an interrupt handler function, then mark the register
   3761  1.1  mrg      stores as volatile.  This will prevent the instruction scheduler
   3762  1.1  mrg      from scrambling the order of register saves.  */
   3763  1.1  mrg   const int volatile_p = current_frame_info.interrupt;
   3764  1.1  mrg   int regno;
   3765  1.1  mrg 
   3766  1.1  mrg   /* Allocate the stack space.  */
   3767  1.1  mrg   emit_frame_insn (gen_addsi3_flags (stack_pointer_rtx, stack_pointer_rtx,
   3768  1.1  mrg 				     GEN_INT (-alloc)));
   3769  1.1  mrg 
   3770  1.1  mrg   for (regno = low_regno; regno <= high_regno; regno++)
   3771  1.1  mrg     {
   3772  1.1  mrg       enum reg_type reg_type = GET_REG_TYPE (regno);
   3773  1.1  mrg       int mask_bit = 1 << (regno - first_regno[reg_type]);
   3774  1.1  mrg       rtx insn;
   3775  1.1  mrg 
   3776  1.1  mrg       if (current_frame_info.mask[reg_type] & mask_bit)
   3777  1.1  mrg 	{
   3778  1.1  mrg 	  offset -= reg_type_size[reg_type];
   3779  1.1  mrg 	  switch (reg_type)
   3780  1.1  mrg 	    {
   3781  1.1  mrg 	    case general:
   3782  1.1  mrg 	      {
   3783  1.1  mrg 		rtx mem
   3784  1.1  mrg 		  = gen_frame_mem (SImode,
   3785  1.1  mrg 				   plus_constant (Pmode,
   3786  1.1  mrg 						  stack_pointer_rtx, offset));
   3787  1.1  mrg 		MEM_VOLATILE_P (mem) = volatile_p;
   3788  1.1  mrg 		emit_frame_insn (gen_movsi (mem, gen_rtx_REG (SImode, regno)));
   3789  1.1  mrg 	      }
   3790  1.1  mrg 	      break;
   3791  1.1  mrg 
   3792  1.1  mrg 	    case mdb:
   3793  1.1  mrg 	      {
   3794  1.1  mrg 		rtx tmp = gen_rtx_REG (DImode, PROLOGUE_TMP_REGNUM);
   3795  1.1  mrg 		rtx mem
   3796  1.1  mrg 		  = gen_frame_mem (DImode,
   3797  1.1  mrg 				   plus_constant (Pmode,
   3798  1.1  mrg 						  stack_pointer_rtx, offset));
   3799  1.1  mrg 		rtx reg = gen_rtx_REG (DImode, regno);
   3800  1.1  mrg 		MEM_VOLATILE_P (mem) = volatile_p;
   3801  1.1  mrg 		emit_insn (gen_movdi (tmp, reg));
   3802  1.1  mrg 		/* Do not generate CFI if in interrupt handler.  */
   3803  1.1  mrg 		if (volatile_p)
   3804  1.1  mrg 		  emit_insn (gen_movdi (mem, tmp));
   3805  1.1  mrg 		else
   3806  1.1  mrg 		  {
   3807  1.1  mrg 		    insn = emit_frame_insn (gen_movdi (mem, tmp));
   3808  1.1  mrg 		    add_reg_note (insn, REG_FRAME_RELATED_EXPR,
   3809  1.1  mrg 				  gen_rtx_SET (mem, reg));
   3810  1.1  mrg 		  }
   3811  1.1  mrg 	      }
   3812  1.1  mrg 	      break;
   3813  1.1  mrg 
   3814  1.1  mrg 	    case mdc:
   3815  1.1  mrg 	      {
   3816  1.1  mrg 		rtx tmp = gen_rtx_REG (SImode, PROLOGUE_TMP_REGNUM);
   3817  1.1  mrg 		rtx mem
   3818  1.1  mrg 		  = gen_frame_mem (SImode,
   3819  1.1  mrg 				   plus_constant (Pmode,
   3820  1.1  mrg 						  stack_pointer_rtx, offset));
   3821  1.1  mrg 		rtx reg = gen_rtx_REG (SImode, regno);
   3822  1.1  mrg 		MEM_VOLATILE_P (mem) = volatile_p;
   3823  1.1  mrg 		emit_insn (gen_movsi (tmp, reg));
   3824  1.1  mrg 		insn = emit_frame_insn (gen_movsi (mem, tmp));
   3825  1.1  mrg 		add_reg_note (insn, REG_FRAME_RELATED_EXPR,
   3826  1.1  mrg 			      gen_rtx_SET (mem, reg));
   3827  1.1  mrg 	      }
   3828  1.1  mrg 	      break;
   3829  1.1  mrg 
   3830  1.1  mrg 	    case floating:
   3831  1.1  mrg 	      {
   3832  1.1  mrg 		rtx tmp = gen_rtx_REG (SFmode, PROLOGUE_TMP_REGNUM);
   3833  1.1  mrg 		rtx mem
   3834  1.1  mrg 		  = gen_frame_mem (SFmode,
   3835  1.1  mrg 				   plus_constant (Pmode,
   3836  1.1  mrg 						  stack_pointer_rtx, offset));
   3837  1.1  mrg 		rtx reg = gen_rtx_REG (SFmode, regno);
   3838  1.1  mrg 		MEM_VOLATILE_P (mem) = volatile_p;
   3839  1.1  mrg 		emit_insn (gen_movsf (tmp, reg));
   3840  1.1  mrg 		insn = emit_frame_insn (gen_movsf (mem, tmp));
   3841  1.1  mrg 		add_reg_note (insn, REG_FRAME_RELATED_EXPR,
   3842  1.1  mrg 			      gen_rtx_SET (mem, reg));
   3843  1.1  mrg 	      }
   3844  1.1  mrg 	      break;
   3845  1.1  mrg 
   3846  1.1  mrg 	    default:
   3847  1.1  mrg 	      break;
   3848  1.1  mrg 	    }
   3849  1.1  mrg 	}
   3850  1.1  mrg     }
   3851  1.1  mrg }
   3852  1.1  mrg 
   3853  1.1  mrg /* This function generates the code for function entry.  */
   3854  1.1  mrg 
   3855  1.1  mrg void
   3856  1.1  mrg visium_expand_prologue (void)
   3857  1.1  mrg {
   3858  1.1  mrg   const int frame_size = visium_compute_frame_size (get_frame_size ());
   3859  1.1  mrg   const int save_area_size = current_frame_info.save_area_size;
   3860  1.1  mrg   const int reg_size1 = current_frame_info.reg_size1;
   3861  1.1  mrg   const int max_reg1 = current_frame_info.max_reg1;
   3862  1.1  mrg   const int reg_size2 = current_frame_info.reg_size2;
   3863  1.1  mrg   const int var_size = current_frame_info.var_size;
   3864  1.1  mrg   const int save_fp = current_frame_info.save_fp;
   3865  1.1  mrg   const int save_lr = current_frame_info.save_lr;
   3866  1.1  mrg   const int lr_slot = current_frame_info.lr_slot;
   3867  1.1  mrg   const int local_frame_offset
   3868  1.1  mrg     = (save_fp + save_lr + lr_slot) * UNITS_PER_WORD;
   3869  1.1  mrg   const int combine = current_frame_info.combine;
   3870  1.1  mrg   int reg_size;
   3871  1.1  mrg   int first_reg;
   3872  1.1  mrg   int fsize;
   3873  1.1  mrg 
   3874  1.1  mrg   /* Save the frame size for future references.  */
   3875  1.1  mrg   visium_frame_size = frame_size;
   3876  1.1  mrg 
   3877  1.1  mrg   if (flag_stack_usage_info)
   3878  1.1  mrg     current_function_static_stack_size = frame_size;
   3879  1.1  mrg 
   3880  1.1  mrg   /* If the registers have to be stacked in 2 blocks, stack the first one.  */
   3881  1.1  mrg   if (reg_size2)
   3882  1.1  mrg     {
   3883  1.1  mrg       visium_save_regs (reg_size1 + save_area_size, reg_size1, 0, max_reg1);
   3884  1.1  mrg       reg_size = reg_size2;
   3885  1.1  mrg       first_reg = max_reg1 + 1;
   3886  1.1  mrg       fsize = local_frame_offset + var_size + reg_size2;
   3887  1.1  mrg     }
   3888  1.1  mrg   else
   3889  1.1  mrg     {
   3890  1.1  mrg       reg_size = reg_size1;
   3891  1.1  mrg       first_reg = 0;
   3892  1.1  mrg       fsize = local_frame_offset + var_size + reg_size1 + save_area_size;
   3893  1.1  mrg     }
   3894  1.1  mrg 
   3895  1.1  mrg   /* If we can't combine register stacking with variable allocation, partially
   3896  1.1  mrg      allocate and stack the (remaining) registers now.  */
   3897  1.1  mrg   if (reg_size && !combine)
   3898  1.1  mrg     visium_save_regs (fsize - local_frame_offset - var_size, reg_size,
   3899  1.1  mrg 		      first_reg, FIRST_PSEUDO_REGISTER - 1);
   3900  1.1  mrg 
   3901  1.1  mrg   /* If we can combine register stacking with variable allocation, fully
   3902  1.1  mrg      allocate and stack the (remaining) registers now.  */
   3903  1.1  mrg   if (reg_size && combine)
   3904  1.1  mrg     visium_save_regs (fsize, local_frame_offset + var_size + reg_size,
   3905  1.1  mrg 		      first_reg, FIRST_PSEUDO_REGISTER - 1);
   3906  1.1  mrg 
   3907  1.1  mrg   /* Otherwise space may still need to be allocated for the variables.  */
   3908  1.1  mrg   else if (fsize)
   3909  1.1  mrg     {
   3910  1.1  mrg       const int alloc_size = reg_size ? local_frame_offset + var_size : fsize;
   3911  1.1  mrg 
   3912  1.1  mrg       if (alloc_size > 65535)
   3913  1.1  mrg 	{
   3914  1.1  mrg 	  rtx tmp = gen_rtx_REG (SImode, PROLOGUE_TMP_REGNUM), insn;
   3915  1.1  mrg 	  emit_insn (gen_movsi (tmp, GEN_INT (alloc_size)));
   3916  1.1  mrg 	  insn = emit_frame_insn (gen_subsi3_flags (stack_pointer_rtx,
   3917  1.1  mrg 						    stack_pointer_rtx,
   3918  1.1  mrg 						    tmp));
   3919  1.1  mrg 	  add_reg_note (insn, REG_FRAME_RELATED_EXPR,
   3920  1.1  mrg 			gen_rtx_SET (stack_pointer_rtx,
   3921  1.1  mrg 				     gen_rtx_PLUS (Pmode, stack_pointer_rtx,
   3922  1.1  mrg 						   GEN_INT (-alloc_size))));
   3923  1.1  mrg 	}
   3924  1.1  mrg       else
   3925  1.1  mrg 	emit_frame_insn (gen_addsi3_flags (stack_pointer_rtx,
   3926  1.1  mrg 					   stack_pointer_rtx,
   3927  1.1  mrg 					   GEN_INT (-alloc_size)));
   3928  1.1  mrg     }
   3929  1.1  mrg 
   3930  1.1  mrg   if (save_fp)
   3931  1.1  mrg     emit_frame_insn (gen_movsi (gen_frame_mem (SImode, stack_pointer_rtx),
   3932  1.1  mrg 				hard_frame_pointer_rtx));
   3933  1.1  mrg 
   3934  1.1  mrg   if (frame_pointer_needed)
   3935  1.1  mrg     emit_frame_insn (gen_stack_save ());
   3936  1.1  mrg 
   3937  1.1  mrg   if (save_lr)
   3938  1.1  mrg     {
   3939  1.1  mrg       rtx base_rtx, mem;
   3940  1.1  mrg 
   3941  1.1  mrg       /* Normally the frame pointer and link register get saved via
   3942  1.1  mrg          write.l (sp),fp
   3943  1.1  mrg          move.l  fp,sp
   3944  1.1  mrg          write.l 1(sp),r21
   3945  1.1  mrg 
   3946  1.1  mrg          Indexing off sp rather than fp to store the link register
   3947  1.1  mrg          avoids presenting the instruction scheduler with an initial
   3948  1.1  mrg          pipeline hazard.  If however the frame is needed for eg.
   3949  1.1  mrg          __builtin_return_address which needs to retrieve the saved
   3950  1.1  mrg          value of the link register from the stack at fp + 4 then
   3951  1.1  mrg          indexing from sp can confuse the dataflow, causing the link
   3952  1.1  mrg          register to be retrieved before it has been saved.  */
   3953  1.1  mrg       if (cfun->machine->frame_needed)
   3954  1.1  mrg 	base_rtx = hard_frame_pointer_rtx;
   3955  1.1  mrg       else
   3956  1.1  mrg 	base_rtx = stack_pointer_rtx;
   3957  1.1  mrg 
   3958  1.1  mrg       mem = gen_frame_mem (SImode,
   3959  1.1  mrg 			   plus_constant (Pmode,
   3960  1.1  mrg 					  base_rtx, save_fp * UNITS_PER_WORD));
   3961  1.1  mrg       emit_frame_insn (gen_movsi (mem, gen_rtx_REG (SImode, LINK_REGNUM)));
   3962  1.1  mrg     }
   3963  1.1  mrg }
   3964  1.1  mrg 
   3965  1.1  mrg static GTY(()) rtx cfa_restores;
   3966  1.1  mrg 
   3967  1.1  mrg /* Queue a REG_CFA_RESTORE note until next stack manipulation insn.  */
   3968  1.1  mrg 
   3969  1.1  mrg static void
   3970  1.1  mrg visium_add_cfa_restore_note (rtx reg)
   3971  1.1  mrg {
   3972  1.1  mrg   cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
   3973  1.1  mrg }
   3974  1.1  mrg 
   3975  1.1  mrg /* Add queued REG_CFA_RESTORE notes to INSN, if any.  */
   3976  1.1  mrg 
   3977  1.1  mrg static void
   3978  1.1  mrg visium_add_queued_cfa_restore_notes (rtx insn)
   3979  1.1  mrg {
   3980  1.1  mrg   rtx last;
   3981  1.1  mrg   if (!cfa_restores)
   3982  1.1  mrg     return;
   3983  1.1  mrg   for (last = cfa_restores; XEXP (last, 1); last = XEXP (last, 1))
   3984  1.1  mrg     ;
   3985  1.1  mrg   XEXP (last, 1) = REG_NOTES (insn);
   3986  1.1  mrg   REG_NOTES (insn) = cfa_restores;
   3987  1.1  mrg   cfa_restores = NULL_RTX;
   3988  1.1  mrg }
   3989  1.1  mrg 
   3990  1.1  mrg /* Restore the registers LOW_REGNO to HIGH_REGNO from the save area at OFFSET
   3991  1.1  mrg    from the stack pointer and pop DEALLOC bytes off the stack.  */
   3992  1.1  mrg 
   3993  1.1  mrg static void
   3994  1.1  mrg visium_restore_regs (int dealloc, int offset, int high_regno, int low_regno)
   3995  1.1  mrg {
   3996  1.1  mrg   /* If this is an interrupt handler function, then mark the register
   3997  1.1  mrg      restores as volatile.  This will prevent the instruction scheduler
   3998  1.1  mrg      from scrambling the order of register restores.  */
   3999  1.1  mrg   const int volatile_p = current_frame_info.interrupt;
   4000  1.1  mrg   int r30_offset = -1;
   4001  1.1  mrg   int regno;
   4002  1.1  mrg 
   4003  1.1  mrg   for (regno = high_regno; regno >= low_regno; --regno)
   4004  1.1  mrg     {
   4005  1.1  mrg       enum reg_type reg_type = GET_REG_TYPE (regno);
   4006  1.1  mrg       int mask_bit = 1 << (regno - first_regno[reg_type]);
   4007  1.1  mrg 
   4008  1.1  mrg       if (current_frame_info.mask[reg_type] & mask_bit)
   4009  1.1  mrg 	{
   4010  1.1  mrg 	  switch (reg_type)
   4011  1.1  mrg 	    {
   4012  1.1  mrg 	    case general:
   4013  1.1  mrg 	      /* Postpone restoring the interrupted context registers
   4014  1.1  mrg 	         until last, since they need to be preceded by a dsi.  */
   4015  1.1  mrg 	      if (regno == 29)
   4016  1.1  mrg 		;
   4017  1.1  mrg 	      else if (regno == 30)
   4018  1.1  mrg 		r30_offset = offset;
   4019  1.1  mrg 	      else
   4020  1.1  mrg 		{
   4021  1.1  mrg 		  rtx mem
   4022  1.1  mrg 		    = gen_frame_mem (SImode,
   4023  1.1  mrg 				     plus_constant (Pmode,
   4024  1.1  mrg 						    stack_pointer_rtx,
   4025  1.1  mrg 						    offset));
   4026  1.1  mrg 		  rtx reg = gen_rtx_REG (SImode, regno);
   4027  1.1  mrg 		  MEM_VOLATILE_P (mem) = volatile_p;
   4028  1.1  mrg 		  emit_insn (gen_movsi (reg, mem));
   4029  1.1  mrg 		  visium_add_cfa_restore_note (reg);
   4030  1.1  mrg 		}
   4031  1.1  mrg 	      break;
   4032  1.1  mrg 
   4033  1.1  mrg 	    case mdb:
   4034  1.1  mrg 	      {
   4035  1.1  mrg 		rtx tmp = gen_rtx_REG (DImode, PROLOGUE_TMP_REGNUM);
   4036  1.1  mrg 		rtx mem
   4037  1.1  mrg 		  = gen_frame_mem (DImode,
   4038  1.1  mrg 				   plus_constant (Pmode,
   4039  1.1  mrg 						  stack_pointer_rtx, offset));
   4040  1.1  mrg 		rtx reg = gen_rtx_REG (DImode, regno);
   4041  1.1  mrg 		MEM_VOLATILE_P (mem) = volatile_p;
   4042  1.1  mrg 		emit_insn (gen_movdi (tmp, mem));
   4043  1.1  mrg 		emit_insn (gen_movdi (reg, tmp));
   4044  1.1  mrg 		/* Do not generate CFI if in interrupt handler.  */
   4045  1.1  mrg 		if (!volatile_p)
   4046  1.1  mrg 		  visium_add_cfa_restore_note (reg);
   4047  1.1  mrg 	      }
   4048  1.1  mrg 	      break;
   4049  1.1  mrg 
   4050  1.1  mrg 	    case mdc:
   4051  1.1  mrg 	      {
   4052  1.1  mrg 		rtx tmp = gen_rtx_REG (SImode, PROLOGUE_TMP_REGNUM);
   4053  1.1  mrg 		rtx mem
   4054  1.1  mrg 		  = gen_frame_mem (SImode,
   4055  1.1  mrg 				   plus_constant (Pmode,
   4056  1.1  mrg 						  stack_pointer_rtx, offset));
   4057  1.1  mrg 		rtx reg = gen_rtx_REG (SImode, regno);
   4058  1.1  mrg 		MEM_VOLATILE_P (mem) = volatile_p;
   4059  1.1  mrg 		emit_insn (gen_movsi (tmp, mem));
   4060  1.1  mrg 		emit_insn (gen_movsi (reg, tmp));
   4061  1.1  mrg 		visium_add_cfa_restore_note (reg);
   4062  1.1  mrg 	      }
   4063  1.1  mrg 	      break;
   4064  1.1  mrg 
   4065  1.1  mrg 	    case floating:
   4066  1.1  mrg 	      {
   4067  1.1  mrg 		rtx tmp = gen_rtx_REG (SFmode, PROLOGUE_TMP_REGNUM);
   4068  1.1  mrg 		rtx mem
   4069  1.1  mrg 		  = gen_frame_mem (SFmode,
   4070  1.1  mrg 				   plus_constant (Pmode,
   4071  1.1  mrg 						  stack_pointer_rtx, offset));
   4072  1.1  mrg 		rtx reg = gen_rtx_REG (SFmode, regno);
   4073  1.1  mrg 		MEM_VOLATILE_P (mem) = volatile_p;
   4074  1.1  mrg 		emit_insn (gen_movsf (tmp, mem));
   4075  1.1  mrg 		emit_insn (gen_movsf (reg, tmp));
   4076  1.1  mrg 		visium_add_cfa_restore_note (reg);
   4077  1.1  mrg 	      }
   4078  1.1  mrg 	      break;
   4079  1.1  mrg 
   4080  1.1  mrg 	    default:
   4081  1.1  mrg 	      break;
   4082  1.1  mrg 	    }
   4083  1.1  mrg 
   4084  1.1  mrg 	  offset += reg_type_size[reg_type];
   4085  1.1  mrg 	}
   4086  1.1  mrg     }
   4087  1.1  mrg 
   4088  1.1  mrg   /* If the interrupted context needs to be restored, precede the
   4089  1.1  mrg      restores of r29 and r30 by a dsi.  */
   4090  1.1  mrg   if (r30_offset >= 0)
   4091  1.1  mrg     {
   4092  1.1  mrg       emit_insn (gen_dsi ());
   4093  1.1  mrg       emit_move_insn (gen_rtx_REG (SImode, 30),
   4094  1.1  mrg 		      gen_frame_mem (SImode,
   4095  1.1  mrg 				     plus_constant (Pmode,
   4096  1.1  mrg 						    stack_pointer_rtx,
   4097  1.1  mrg 						    r30_offset)));
   4098  1.1  mrg       emit_move_insn (gen_rtx_REG (SImode, 29),
   4099  1.1  mrg 		      gen_frame_mem (SImode,
   4100  1.1  mrg 				     plus_constant (Pmode,
   4101  1.1  mrg 						    stack_pointer_rtx,
   4102  1.1  mrg 						    r30_offset + 4)));
   4103  1.1  mrg     }
   4104  1.1  mrg 
   4105  1.1  mrg   /* Deallocate the stack space.  */
   4106  1.1  mrg   rtx insn = emit_frame_insn (gen_stack_pop (GEN_INT (dealloc)));
   4107  1.1  mrg   add_reg_note (insn, REG_FRAME_RELATED_EXPR,
   4108  1.1  mrg 		gen_rtx_SET (stack_pointer_rtx,
   4109  1.1  mrg 			     gen_rtx_PLUS (Pmode, stack_pointer_rtx,
   4110  1.1  mrg 					   GEN_INT (dealloc))));
   4111  1.1  mrg   visium_add_queued_cfa_restore_notes (insn);
   4112  1.1  mrg }
   4113  1.1  mrg 
   4114  1.1  mrg /* This function generates the code for function exit.  */
   4115  1.1  mrg 
   4116  1.1  mrg void
   4117  1.1  mrg visium_expand_epilogue (void)
   4118  1.1  mrg {
   4119  1.1  mrg   const int save_area_size = current_frame_info.save_area_size;
   4120  1.1  mrg   const int reg_size1 = current_frame_info.reg_size1;
   4121  1.1  mrg   const int max_reg1 = current_frame_info.max_reg1;
   4122  1.1  mrg   const int reg_size2 = current_frame_info.reg_size2;
   4123  1.1  mrg   const int var_size = current_frame_info.var_size;
   4124  1.1  mrg   const int restore_fp = current_frame_info.save_fp;
   4125  1.1  mrg   const int restore_lr = current_frame_info.save_lr;
   4126  1.1  mrg   const int lr_slot = current_frame_info.lr_slot;
   4127  1.1  mrg   const int local_frame_offset
   4128  1.1  mrg     = (restore_fp + restore_lr + lr_slot) * UNITS_PER_WORD;
   4129  1.1  mrg   const int combine = current_frame_info.combine;
   4130  1.1  mrg   int reg_size;
   4131  1.1  mrg   int last_reg;
   4132  1.1  mrg   int fsize;
   4133  1.1  mrg 
   4134  1.1  mrg   /* Do not bother restoring the stack pointer if it hasn't been changed in
   4135  1.1  mrg      the function since it was saved _after_ the allocation of the frame.  */
   4136  1.1  mrg   if (!crtl->sp_is_unchanging)
   4137  1.1  mrg     emit_insn (gen_stack_restore ());
   4138  1.1  mrg 
   4139  1.1  mrg   /* Restore the frame pointer if necessary.  The usual code would be:
   4140  1.1  mrg 
   4141  1.1  mrg        move.l  sp,fp
   4142  1.1  mrg        read.l  fp,(sp)
   4143  1.1  mrg 
   4144  1.1  mrg      but for the MCM this constitutes a stall/hazard so it is changed to:
   4145  1.1  mrg 
   4146  1.1  mrg        move.l  sp,fp
   4147  1.1  mrg        read.l  fp,(fp)
   4148  1.1  mrg 
   4149  1.1  mrg      if the stack pointer has actually been restored.  */
   4150  1.1  mrg   if (restore_fp)
   4151  1.1  mrg     {
   4152  1.1  mrg       rtx src;
   4153  1.1  mrg 
   4154  1.1  mrg       if (TARGET_MCM && !crtl->sp_is_unchanging)
   4155  1.1  mrg 	src = gen_frame_mem (SImode, hard_frame_pointer_rtx);
   4156  1.1  mrg       else
   4157  1.1  mrg 	src = gen_frame_mem (SImode, stack_pointer_rtx);
   4158  1.1  mrg 
   4159  1.1  mrg       rtx insn = emit_frame_insn (gen_movsi (hard_frame_pointer_rtx, src));
   4160  1.1  mrg       add_reg_note (insn, REG_CFA_ADJUST_CFA,
   4161  1.1  mrg 		    gen_rtx_SET (stack_pointer_rtx,
   4162  1.1  mrg 				 hard_frame_pointer_rtx));
   4163  1.1  mrg       visium_add_cfa_restore_note (hard_frame_pointer_rtx);
   4164  1.1  mrg     }
   4165  1.1  mrg 
   4166  1.1  mrg   /* Restore the link register if necessary.  */
   4167  1.1  mrg   if (restore_lr)
   4168  1.1  mrg     {
   4169  1.1  mrg       rtx mem = gen_frame_mem (SImode,
   4170  1.1  mrg 			       plus_constant (Pmode,
   4171  1.1  mrg 					      stack_pointer_rtx,
   4172  1.1  mrg 					      restore_fp * UNITS_PER_WORD));
   4173  1.1  mrg       rtx reg = gen_rtx_REG (SImode, LINK_REGNUM);
   4174  1.1  mrg       emit_insn (gen_movsi (reg, mem));
   4175  1.1  mrg       visium_add_cfa_restore_note (reg);
   4176  1.1  mrg     }
   4177  1.1  mrg 
   4178  1.1  mrg   /* If we have two blocks of registers, deal with the second one first.  */
   4179  1.1  mrg   if (reg_size2)
   4180  1.1  mrg     {
   4181  1.1  mrg       reg_size = reg_size2;
   4182  1.1  mrg       last_reg = max_reg1 + 1;
   4183  1.1  mrg       fsize = local_frame_offset + var_size + reg_size2;
   4184  1.1  mrg     }
   4185  1.1  mrg   else
   4186  1.1  mrg     {
   4187  1.1  mrg       reg_size = reg_size1;
   4188  1.1  mrg       last_reg = 0;
   4189  1.1  mrg       fsize = local_frame_offset + var_size + reg_size1 + save_area_size;
   4190  1.1  mrg     }
   4191  1.1  mrg 
   4192  1.1  mrg   /* If the variable allocation could be combined with register stacking,
   4193  1.1  mrg      restore the (remaining) registers and fully deallocate now.  */
   4194  1.1  mrg   if (reg_size && combine)
   4195  1.1  mrg     visium_restore_regs (fsize, local_frame_offset + var_size,
   4196  1.1  mrg 			 FIRST_PSEUDO_REGISTER - 1, last_reg);
   4197  1.1  mrg 
   4198  1.1  mrg   /* Otherwise deallocate the variables first.  */
   4199  1.1  mrg   else if (fsize)
   4200  1.1  mrg     {
   4201  1.1  mrg       const int pop_size = reg_size ? local_frame_offset + var_size : fsize;
   4202  1.1  mrg       rtx insn;
   4203  1.1  mrg 
   4204  1.1  mrg       if (pop_size > 65535)
   4205  1.1  mrg 	{
   4206  1.1  mrg 	  rtx tmp = gen_rtx_REG (SImode, PROLOGUE_TMP_REGNUM);
   4207  1.1  mrg 	  emit_move_insn (tmp, GEN_INT (pop_size));
   4208  1.1  mrg 	  insn = emit_frame_insn (gen_stack_pop (tmp));
   4209  1.1  mrg         }
   4210  1.1  mrg       else
   4211  1.1  mrg 	insn = emit_frame_insn (gen_stack_pop (GEN_INT (pop_size)));
   4212  1.1  mrg       add_reg_note (insn, REG_FRAME_RELATED_EXPR,
   4213  1.1  mrg 		    gen_rtx_SET (stack_pointer_rtx,
   4214  1.1  mrg 				 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
   4215  1.1  mrg 					       GEN_INT (pop_size))));
   4216  1.1  mrg       visium_add_queued_cfa_restore_notes (insn);
   4217  1.1  mrg     }
   4218  1.1  mrg 
   4219  1.1  mrg   /* If the variable allocation couldn't be combined with register stacking,
   4220  1.1  mrg      restore the (remaining) registers now and partially deallocate.  */
   4221  1.1  mrg   if (reg_size && !combine)
   4222  1.1  mrg     visium_restore_regs (fsize - local_frame_offset - var_size, 0,
   4223  1.1  mrg 			 FIRST_PSEUDO_REGISTER - 1, last_reg);
   4224  1.1  mrg 
   4225  1.1  mrg   /* If the first block of registers has yet to be restored, do it now.  */
   4226  1.1  mrg   if (reg_size2)
   4227  1.1  mrg     visium_restore_regs (reg_size1 + save_area_size, 0, max_reg1, 0);
   4228  1.1  mrg 
   4229  1.1  mrg   /* If this is an exception return, make the necessary stack adjustment.  */
   4230  1.1  mrg   if (crtl->calls_eh_return)
   4231  1.1  mrg     emit_insn (gen_stack_pop (EH_RETURN_STACKADJ_RTX));
   4232  1.1  mrg }
   4233  1.1  mrg 
   4234  1.1  mrg /* Return true if it is appropriate to emit `return' instructions in the
   4235  1.1  mrg    body of a function.  */
   4236  1.1  mrg 
   4237  1.1  mrg bool
   4238  1.1  mrg visium_can_use_return_insn_p (void)
   4239  1.1  mrg {
   4240  1.1  mrg   return reload_completed
   4241  1.1  mrg 	 && visium_frame_size == 0
   4242  1.1  mrg 	 && !visium_interrupt_function_p ();
   4243  1.1  mrg }
   4244  1.1  mrg 
   4245  1.1  mrg /* Return the register class required for an intermediate register used to
   4246  1.1  mrg    copy a register of RCLASS from/to X.  If no such intermediate register is
   4247  1.1  mrg    required, return NO_REGS.  If more than one such intermediate register is
   4248  1.1  mrg    required, describe the one that is closest in the copy chain to the reload
   4249  1.1  mrg    register.  */
   4250  1.1  mrg 
   4251  1.1  mrg static reg_class_t
   4252  1.1  mrg visium_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
   4253  1.1  mrg 			 reg_class_t rclass,
   4254  1.1  mrg 			 machine_mode mode ATTRIBUTE_UNUSED,
   4255  1.1  mrg 			 secondary_reload_info *sri ATTRIBUTE_UNUSED)
   4256  1.1  mrg {
   4257  1.1  mrg   int regno = true_regnum (x);
   4258  1.1  mrg 
   4259  1.1  mrg   /* For MDB, MDC and FP_REGS, a general register is needed for a move to
   4260  1.1  mrg      or from memory. */
   4261  1.1  mrg   if (regno == -1 && (rclass == MDB || rclass == MDC || rclass == FP_REGS))
   4262  1.1  mrg     return GENERAL_REGS;
   4263  1.1  mrg 
   4264  1.1  mrg   /* Moves between MDB, MDC and FP_REGS also require a general register. */
   4265  1.1  mrg   else if (((regno == R_MDB || regno == R_MDC) && rclass == FP_REGS)
   4266  1.1  mrg       || (FP_REGISTER_P (regno) && (rclass == MDB || rclass == MDC)))
   4267  1.1  mrg     return GENERAL_REGS;
   4268  1.1  mrg 
   4269  1.1  mrg   /* Finally an (unlikely ?) move between MDB and MDC needs a general reg. */
   4270  1.1  mrg   else if ((regno == R_MDB && rclass == MDC)
   4271  1.1  mrg 	   || (rclass == MDB && regno == R_MDC))
   4272  1.1  mrg     return GENERAL_REGS;
   4273  1.1  mrg 
   4274  1.1  mrg   return NO_REGS;
   4275  1.1  mrg }
   4276  1.1  mrg 
   4277  1.1  mrg /* Return true if pseudos that have been assigned to registers of RCLASS
   4278  1.1  mrg    would likely be spilled because registers of RCLASS are needed for
   4279  1.1  mrg    spill registers.  */
   4280  1.1  mrg 
   4281  1.1  mrg static bool
   4282  1.1  mrg visium_class_likely_spilled_p (reg_class_t rclass ATTRIBUTE_UNUSED)
   4283  1.1  mrg {
   4284  1.1  mrg   /* Return false for classes R1, R2 and R3, which are intended to be used
   4285  1.1  mrg      only in the source code in conjunction with block move instructions.  */
   4286  1.1  mrg   return false;
   4287  1.1  mrg }
   4288  1.1  mrg 
   4289  1.1  mrg /* Return the register number if OP is a REG or a SUBREG of a REG, and
   4290  1.1  mrg    INVALID_REGNUM in all the other cases.  */
   4291  1.1  mrg 
   4292  1.1  mrg unsigned int
   4293  1.1  mrg reg_or_subreg_regno (rtx op)
   4294  1.1  mrg {
   4295  1.1  mrg   unsigned int regno;
   4296  1.1  mrg 
   4297  1.1  mrg   if (GET_CODE (op) == REG)
   4298  1.1  mrg     regno = REGNO (op);
   4299  1.1  mrg   else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
   4300  1.1  mrg     {
   4301  1.1  mrg       if (REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
   4302  1.1  mrg 	regno = subreg_regno (op);
   4303  1.1  mrg       else
   4304  1.1  mrg 	regno = REGNO (SUBREG_REG (op));
   4305  1.1  mrg     }
   4306  1.1  mrg   else
   4307  1.1  mrg     regno = INVALID_REGNUM;
   4308  1.1  mrg 
   4309  1.1  mrg   return regno;
   4310  1.1  mrg }
   4311  1.1  mrg 
   4312  1.1  mrg /* Implement TARGET_CAN_CHANGE_MODE_CLASS.
   4313  1.1  mrg 
   4314  1.1  mrg    It's not obvious from the documentation of the hook that MDB cannot
   4315  1.1  mrg    change mode.  However difficulties arise from expressions of the form
   4316  1.1  mrg 
   4317  1.1  mrg    (subreg:SI (reg:DI R_MDB) 0)
   4318  1.1  mrg 
   4319  1.1  mrg    There is no way to convert that reference to a single machine
   4320  1.1  mrg    register and, without the following definition, reload will quietly
   4321  1.1  mrg    convert it to
   4322  1.1  mrg 
   4323  1.1  mrg    (reg:SI R_MDB).  */
   4324  1.1  mrg 
   4325  1.1  mrg static bool
   4326  1.1  mrg visium_can_change_mode_class (machine_mode from, machine_mode to,
   4327  1.1  mrg 			      reg_class_t rclass)
   4328  1.1  mrg {
   4329  1.1  mrg   return (rclass != MDB || GET_MODE_SIZE (from) == GET_MODE_SIZE (to));
   4330  1.1  mrg }
   4331  1.1  mrg 
   4332  1.1  mrg #include "gt-visium.h"
   4333