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