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