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