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