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