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