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