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