1 /* Subroutines for insn-output.c for Motorola 88000.
2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002 Free Software Foundation, Inc.
4 Contributed by Michael Tiemann (tiemann@mcc.com)
5 Currently maintained by (gcc@dg-rtp.dg.com)
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING. If not, write to
21 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA. */
23
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "rtl.h"
29 #include "regs.h"
30 #include "hard-reg-set.h"
31 #include "real.h"
32 #include "insn-config.h"
33 #include "conditions.h"
34 #include "output.h"
35 #include "insn-attr.h"
36 #include "tree.h"
37 #include "function.h"
38 #include "expr.h"
39 #include "libfuncs.h"
40 #include "c-tree.h"
41 #include "flags.h"
42 #include "recog.h"
43 #include "toplev.h"
44 #include "tm_p.h"
45 #include "target.h"
46 #include "target-def.h"
47 #include "tree-gimple.h"
48
49 #ifdef REGISTER_PREFIX
50 const char *m88k_register_prefix = REGISTER_PREFIX;
51 #else
52 const char *m88k_register_prefix = "";
53 #endif
54 char m88k_volatile_code;
55
56 int m88k_fp_offset = 0; /* offset of frame pointer if used */
57 int m88k_stack_size = 0; /* size of allocated stack (including frame) */
58 int m88k_case_index;
59
60 rtx m88k_compare_reg; /* cmp output pseudo register */
61 rtx m88k_compare_op0; /* cmpsi operand 0 */
62 rtx m88k_compare_op1; /* cmpsi operand 1 */
63
64 enum processor_type m88k_cpu; /* target cpu */
65
66 static void m88k_maybe_dead (rtx);
67 static void m88k_output_function_epilogue (FILE *, HOST_WIDE_INT);
68 static rtx m88k_struct_value_rtx (tree, int);
69 static int m88k_adjust_cost (rtx, rtx, rtx, int);
70 static bool m88k_handle_option (size_t, const char *, int);
71 static bool m88k_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
72 tree, bool);
73 static bool m88k_return_in_memory (tree, tree);
74 static void m88k_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
75 tree, int *, int);
76 static tree m88k_build_va_list (void);
77 static tree m88k_gimplify_va_arg (tree, tree, tree *, tree *);
78 static bool m88k_rtx_costs (rtx, int, int, int *);
79 static int m88k_address_cost (rtx);
80 static void m88k_output_file_start (void);
81
82 /* Initialize the GCC target structure. */
83 #if !defined(OBJECT_FORMAT_ELF)
84 #undef TARGET_ASM_BYTE_OP
85 #define TARGET_ASM_BYTE_OP "\tbyte\t"
86 #undef TARGET_ASM_ALIGNED_HI_OP
87 #define TARGET_ASM_ALIGNED_HI_OP "\thalf\t"
88 #undef TARGET_ASM_ALIGNED_SI_OP
89 #define TARGET_ASM_ALIGNED_SI_OP "\tword\t"
90 #undef TARGET_ASM_UNALIGNED_HI_OP
91 #define TARGET_ASM_UNALIGNED_HI_OP "\tuahalf\t"
92 #undef TARGET_ASM_UNALIGNED_SI_OP
93 #define TARGET_ASM_UNALIGNED_SI_OP "\tuaword\t"
94 #endif
95
96 #undef TARGET_ASM_FUNCTION_EPILOGUE
97 #define TARGET_ASM_FUNCTION_EPILOGUE m88k_output_function_epilogue
98
99 #undef TARGET_SCHED_ADJUST_COST
100 #define TARGET_SCHED_ADJUST_COST m88k_adjust_cost
101
102 #undef TARGET_HANDLE_OPTION
103 #define TARGET_HANDLE_OPTION m88k_handle_option
104
105 #undef TARGET_STRUCT_VALUE_RTX
106 #define TARGET_STRUCT_VALUE_RTX m88k_struct_value_rtx
107
108 #undef TARGET_PASS_BY_REFERENCE
109 #define TARGET_PASS_BY_REFERENCE m88k_pass_by_reference
110
111 #undef TARGET_RETURN_IN_MEMORY
112 #define TARGET_RETURN_IN_MEMORY m88k_return_in_memory
113
114 #undef TARGET_PROMOTE_PROTOTYPES
115 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
116
117 #undef TARGET_PROMOTE_FUNCTION_ARGS
118 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
119
120 #undef TARGET_PROMOTE_FUNCTION_RETURN
121 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
122
123 #undef TARGET_SETUP_INCOMING_VARARGS
124 #define TARGET_SETUP_INCOMING_VARARGS m88k_setup_incoming_varargs
125
126 #undef TARGET_BUILD_BUILTIN_VA_LIST
127 #define TARGET_BUILD_BUILTIN_VA_LIST m88k_build_va_list
128
129 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
130 #define TARGET_GIMPLIFY_VA_ARG_EXPR m88k_gimplify_va_arg
131
132 #undef TARGET_RTX_COSTS
133 #define TARGET_RTX_COSTS m88k_rtx_costs
134
135 #undef TARGET_ADDRESS_COST
136 #define TARGET_ADDRESS_COST m88k_address_cost
137
138 #undef TARGET_ASM_FILE_START
139 #define TARGET_ASM_FILE_START m88k_output_file_start
140 /* from elfos.h
141 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
142 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
143 */
144
145 struct gcc_target targetm = TARGET_INITIALIZER;
146
147 /* Worker function for TARGET_STRUCT_VALUE_RTX. */
148
149 static rtx
m88k_struct_value_rtx(tree fntype ATTRIBUTE_UNUSED,int incoming ATTRIBUTE_UNUSED)150 m88k_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
151 int incoming ATTRIBUTE_UNUSED)
152 {
153 return gen_rtx_REG (Pmode, M88K_STRUCT_VALUE_REGNUM);
154 }
155
156 /* Determine what instructions are needed to manufacture the integer VALUE
157 in the given MODE. */
158
159 enum m88k_instruction
classify_integer(enum machine_mode mode,int value)160 classify_integer (enum machine_mode mode, int value)
161 {
162 if (value == 0)
163 return m88k_zero;
164 else if (SMALL_INTVAL (value))
165 return m88k_or;
166 else if (SMALL_INTVAL (-value))
167 return m88k_subu;
168 else if (mode == HImode)
169 return m88k_or_lo16;
170 else if (mode == QImode)
171 return m88k_or_lo8;
172 else if (integer_ok_for_set (value))
173 return m88k_set;
174 else if ((value & 0xffff) == 0)
175 return m88k_oru_hi16;
176 else
177 return m88k_oru_or;
178 }
179
180 /* Return the bit number in a compare word corresponding to CONDITION. */
181
182 int
condition_value(rtx condition)183 condition_value (rtx condition)
184 {
185 switch (GET_CODE (condition))
186 {
187 case UNORDERED:
188 return 0;
189 case ORDERED:
190 return 1;
191 case EQ:
192 return 2;
193 case NE:
194 return 3;
195 case GT:
196 return 4;
197 case LE:
198 return 5;
199 case LT:
200 return 6;
201 case GE:
202 return 7;
203 case GTU:
204 return 8;
205 case LEU:
206 return 9;
207 case LTU:
208 return 10;
209 case GEU:
210 return 11;
211 default:
212 gcc_unreachable ();
213 }
214 }
215
216 bool
integer_ok_for_set(unsigned int value)217 integer_ok_for_set (unsigned int value)
218 {
219 unsigned int mask;
220
221 if (value == 0)
222 return false;
223 /* All the "one" bits must be contiguous. If so, MASK + 1 will be
224 a power of two or zero. */
225 mask = value | (value - 1);
226 return POWER_OF_2_or_0 (mask + 1);
227 }
228
229 const char *
output_load_const_int(enum machine_mode mode,rtx * operands)230 output_load_const_int (enum machine_mode mode, rtx *operands)
231 {
232 static const char *const patterns[] =
233 {
234 "or %0,%#r0,0",
235 "or %0,%#r0,%1",
236 "subu %0,%#r0,%n1",
237 "or %0,%#r0,%h1",
238 "or %0,%#r0,%q1",
239 "set %0,%#r0,%s1",
240 "or.u %0,%#r0,%X1",
241 "or.u %0,%#r0,%X1\n\tor %0,%0,%x1",
242 };
243
244 gcc_assert (REG_P (operands[0])
245 && GET_CODE (operands[1]) == CONST_INT);
246 return patterns[classify_integer (mode, INTVAL (operands[1]))];
247 }
248
249 /* These next two routines assume that floating point numbers are represented
250 in a manner which is consistent between host and target machines. */
251
252 const char *
output_load_const_float(rtx * operands)253 output_load_const_float (rtx *operands)
254 {
255 /* These can return 0 under some circumstances when cross-compiling. */
256 operands[0] = operand_subword (operands[0], 0, 0, SFmode);
257 operands[1] = operand_subword (operands[1], 0, 0, SFmode);
258
259 return output_load_const_int (SImode, operands);
260 }
261
262 const char *
output_load_const_double(rtx * operands)263 output_load_const_double (rtx *operands)
264 {
265 rtx latehalf[2];
266
267 /* These can return zero on some cross-compilers, but there's nothing
268 we can do about it. */
269 latehalf[0] = operand_subword (operands[0], 1, 0, DFmode);
270 latehalf[1] = operand_subword (operands[1], 1, 0, DFmode);
271
272 operands[0] = operand_subword (operands[0], 0, 0, DFmode);
273 operands[1] = operand_subword (operands[1], 0, 0, DFmode);
274
275 output_asm_insn (output_load_const_int (SImode, operands), operands);
276
277 operands[0] = latehalf[0];
278 operands[1] = latehalf[1];
279
280 return output_load_const_int (SImode, operands);
281 }
282
283 const char *
output_load_const_dimode(rtx * operands)284 output_load_const_dimode (rtx *operands)
285 {
286 rtx latehalf[2];
287
288 latehalf[0] = operand_subword (operands[0], 1, 0, DImode);
289 latehalf[1] = operand_subword (operands[1], 1, 0, DImode);
290
291 operands[0] = operand_subword (operands[0], 0, 0, DImode);
292 operands[1] = operand_subword (operands[1], 0, 0, DImode);
293
294 output_asm_insn (output_load_const_int (SImode, operands), operands);
295
296 operands[0] = latehalf[0];
297 operands[1] = latehalf[1];
298
299 return output_load_const_int (SImode, operands);
300 }
301
302 /* Emit insns to move operands[1] into operands[0].
303
304 Return 1 if we have written out everything that needs to be done to
305 do the move. Otherwise, return 0 and the caller will emit the move
306 normally.
307
308 SCRATCH if nonzero can be used as a scratch register for the move
309 operation. It is provided by a SECONDARY_RELOAD_* macro if needed. */
310
311 int
emit_move_sequence(rtx * operands,enum machine_mode mode,rtx scratch)312 emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch)
313 {
314 rtx operand0 = operands[0];
315 rtx operand1 = operands[1];
316
317 if (CONSTANT_P (operand1) && flag_pic
318 && pic_address_needs_scratch (operand1))
319 operands[1] = operand1 = legitimize_address (1, operand1, NULL_RTX,
320 NULL_RTX);
321
322 /* Handle most common case first: storing into a register. */
323 if (register_operand (operand0, mode))
324 {
325 if (register_operand (operand1, mode)
326 || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
327 || GET_CODE (operand1) == HIGH
328 /* Only `general_operands' can come here, so MEM is ok. */
329 || GET_CODE (operand1) == MEM)
330 {
331 /* Run this case quickly. */
332 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
333 return 1;
334 }
335 }
336 else if (GET_CODE (operand0) == MEM)
337 {
338 if (register_operand (operand1, mode)
339 || (operand1 == const0_rtx && GET_MODE_SIZE (mode) <= UNITS_PER_WORD))
340 {
341 /* Run this case quickly. */
342 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
343 return 1;
344 }
345 if (! reload_in_progress && ! reload_completed)
346 {
347 operands[0] = validize_mem (operand0);
348 operands[1] = operand1 = force_reg (mode, operand1);
349 }
350 }
351
352 /* Simplify the source if we need to. */
353 if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
354 {
355 if (GET_CODE (operand1) != CONST_INT
356 && GET_CODE (operand1) != CONST_DOUBLE)
357 {
358 rtx temp = ((reload_in_progress || reload_completed)
359 ? operand0 : NULL_RTX);
360 operands[1] = legitimize_address (flag_pic
361 && symbolic_address_p (operand1),
362 operand1, temp, scratch);
363 if (mode != SImode)
364 operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
365 }
366 }
367
368 /* Now have insn-emit do whatever it normally does. */
369 return 0;
370 }
371
372 /* Return a legitimate reference for ORIG (either an address or a MEM)
373 using the register REG. If PIC and the address is already
374 position-independent, use ORIG. Newly generated position-independent
375 addresses go into a reg. This is REG if nonzero, otherwise we
376 allocate register(s) as necessary. If this is called during reload,
377 and we need a second temp register, then we use SCRATCH, which is
378 provided via the SECONDARY_INPUT_RELOAD_CLASS mechanism. */
379
380 struct rtx_def *
legitimize_address(int pic,rtx orig,rtx reg,rtx scratch)381 legitimize_address (int pic, rtx orig, rtx reg, rtx scratch)
382 {
383 rtx addr = (GET_CODE (orig) == MEM ? XEXP (orig, 0) : orig);
384 rtx new = orig;
385 rtx temp, insn;
386
387 if (pic)
388 {
389 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
390 {
391 if (reg == NULL_RTX)
392 {
393 gcc_assert (!reload_in_progress && !reload_completed);
394 reg = gen_reg_rtx (Pmode);
395 }
396
397 if (flag_pic == 2)
398 {
399 /* If not during reload, allocate another temp reg here for
400 loading in the address, so that these instructions can be
401 optimized properly. */
402 temp = ((reload_in_progress || reload_completed)
403 ? reg : gen_reg_rtx (Pmode));
404
405 /* Must put the SYMBOL_REF inside an UNSPEC here so that cse
406 won't get confused into thinking that these two instructions
407 are loading in the true address of the symbol. If in the
408 future a PIC rtx exists, that should be used instead. */
409 emit_insn (gen_movsi_high_pic (temp, addr));
410 emit_insn (gen_movsi_lo_sum_pic (temp, temp, addr));
411 addr = temp;
412 }
413
414 new = gen_rtx_MEM (Pmode,
415 gen_rtx_PLUS (SImode,
416 pic_offset_table_rtx, addr));
417
418 current_function_uses_pic_offset_table = 1;
419 MEM_READONLY_P (new) = 1;
420 insn = emit_move_insn (reg, new);
421 /* Put a REG_EQUAL note on this insn, so that it can be optimized
422 by loop. */
423 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
424 REG_NOTES (insn));
425 new = reg;
426 }
427 else if (GET_CODE (addr) == CONST)
428 {
429 rtx base;
430
431 if (GET_CODE (XEXP (addr, 0)) == PLUS
432 && XEXP (XEXP (addr, 0), 0) == pic_offset_table_rtx)
433 return orig;
434
435 if (reg == NULL_RTX)
436 {
437 gcc_assert (!reload_in_progress && !reload_completed);
438 reg = gen_reg_rtx (Pmode);
439 }
440
441 gcc_assert (GET_CODE (XEXP (addr, 0)) == PLUS);
442
443 base = legitimize_address (1, XEXP (XEXP (addr, 0), 0), reg,
444 NULL_RTX);
445 addr = legitimize_address (1, XEXP (XEXP (addr, 0), 1),
446 base == reg ? NULL_RTX : reg, NULL_RTX);
447
448 if (GET_CODE (addr) == CONST_INT)
449 {
450 if (ADD_INT (addr))
451 return plus_constant (base, INTVAL (addr));
452 else if (! reload_in_progress && ! reload_completed)
453 addr = force_reg (Pmode, addr);
454 /* We can't create any new registers during reload, so use the
455 SCRATCH reg provided by the reload_insi pattern. */
456 else if (scratch)
457 {
458 emit_move_insn (scratch, addr);
459 addr = scratch;
460 }
461 else
462 /* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS
463 macro needs to be adjusted so that a scratch reg is provided
464 for this address. */
465 gcc_unreachable ();
466 }
467 new = gen_rtx_PLUS (SImode, base, addr);
468 /* Should we set special REG_NOTEs here? */
469 }
470 }
471 else
472 {
473 if (reg == NULL_RTX)
474 {
475 gcc_assert (!reload_in_progress && !reload_completed);
476 reg = gen_reg_rtx (Pmode);
477 }
478
479 emit_insn (gen_rtx_SET (VOIDmode,
480 reg, gen_rtx_HIGH (SImode, addr)));
481 new = gen_rtx_LO_SUM (SImode, reg, addr);
482 }
483
484 if (GET_CODE (orig) == MEM)
485 {
486 new = gen_rtx_MEM (GET_MODE (orig), new);
487 MEM_COPY_ATTRIBUTES (new, orig);
488 }
489 return new;
490 }
491
492 /* Support functions for code to emit a block move. There are two methods
493 used to perform the block move:
494 + call memcpy
495 + produce an inline sequence of ld/st instructions
496 */
497
498 static const enum machine_mode mode_from_align[] =
499 {VOIDmode, QImode, HImode, VOIDmode, SImode,
500 VOIDmode, VOIDmode, VOIDmode, DImode};
501
502 static void block_move_sequence (rtx, rtx, rtx, rtx, int, int);
503
504 /* Emit code to perform a block move. Choose the best method.
505
506 OPERANDS[0] is the destination.
507 OPERANDS[1] is the source.
508 OPERANDS[2] is the size.
509 OPERANDS[3] is the alignment safe to use. */
510
511 void
expand_block_move(rtx dest_mem,rtx src_mem,rtx * operands)512 expand_block_move (rtx dest_mem, rtx src_mem, rtx *operands)
513 {
514 int align = INTVAL (operands[3]);
515 int constp = (GET_CODE (operands[2]) == CONST_INT);
516 int bytes = (constp ? INTVAL (operands[2]) : 0);
517
518 if (constp && bytes <= 0)
519 return;
520
521 /* Determine machine mode to do move with. */
522 if (align > 4 && !TARGET_88110)
523 align = 4;
524 else
525 gcc_assert (align > 0 && align != 3); /* block move invalid alignment. */
526
527 if (constp && bytes <= 3 * align)
528 block_move_sequence (operands[0], dest_mem, operands[1], src_mem,
529 bytes, align);
530
531 else
532 {
533 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "memcpy"), 0,
534 VOIDmode, 3,
535 operands[0], Pmode,
536 operands[1], Pmode,
537 convert_to_mode (TYPE_MODE (sizetype), operands[2],
538 TYPE_UNSIGNED (sizetype)),
539 TYPE_MODE (sizetype));
540 }
541 }
542
543 /* Emit code to perform a block move with an offset sequence of ld/st
544 instructions (..., ld 0, st 1, ld 1, st 0, ...). SIZE and ALIGN are
545 known constants. DEST and SRC are registers. */
546
547 static void
block_move_sequence(rtx dest,rtx dest_mem,rtx src,rtx src_mem,int size,int align)548 block_move_sequence (rtx dest, rtx dest_mem, rtx src, rtx src_mem, int size,
549 int align)
550 {
551 rtx temp[2];
552 enum machine_mode mode[2];
553 int amount[2];
554 int active[2];
555 int phase = 0;
556 int next;
557 int offset_ld = 0;
558 int offset_st = 0;
559
560 active[0] = active[1] = FALSE;
561
562 /* Establish parameters for the first load and for the second load if
563 it is known to be the same mode as the first. */
564 amount[0] = amount[1] = align;
565 mode[0] = mode_from_align[align];
566 temp[0] = gen_reg_rtx (mode[0]);
567 if (size >= 2 * align)
568 {
569 mode[1] = mode[0];
570 temp[1] = gen_reg_rtx (mode[1]);
571 }
572
573 do
574 {
575 next = phase;
576 phase = !phase;
577
578 if (size > 0)
579 {
580 /* Change modes as the sequence tails off. */
581 if (size < amount[next])
582 {
583 amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1));
584 mode[next] = mode_from_align[amount[next]];
585 temp[next] = gen_reg_rtx (mode[next]);
586 }
587 size -= amount[next];
588 emit_move_insn (temp[next],
589 adjust_address (src_mem, mode[next], offset_ld));
590 offset_ld += amount[next];
591 active[next] = TRUE;
592 }
593
594 if (active[phase])
595 {
596 active[phase] = FALSE;
597 emit_move_insn (adjust_address (dest_mem, mode[phase], offset_st),
598 temp[phase]);
599 offset_st += amount[phase];
600 }
601 }
602 while (active[next]);
603 }
604
605 /* Emit the code to do an AND operation. */
606
607 const char *
output_and(rtx operands[])608 output_and (rtx operands[])
609 {
610 unsigned int value;
611
612 if (REG_P (operands[2]))
613 return "and %0,%1,%2";
614
615 value = INTVAL (operands[2]);
616 if (SMALL_INTVAL (value))
617 return "mask %0,%1,%2";
618 else if ((value & 0xffff0000) == 0xffff0000)
619 return "and %0,%1,%x2";
620 else if ((value & 0xffff) == 0xffff)
621 return "and.u %0,%1,%X2";
622 else if ((value & 0xffff) == 0)
623 return "mask.u %0,%1,%X2";
624 else if (integer_ok_for_set (~value))
625 return "clr %0,%1,%S2";
626 else
627 return "and.u %0,%1,%X2\n\tand %0,%0,%x2";
628 }
629
630 /* Emit the code to do an inclusive OR operation. */
631
632 const char *
output_ior(rtx operands[])633 output_ior (rtx operands[])
634 {
635 unsigned int value;
636
637 if (REG_P (operands[2]))
638 return "or %0,%1,%2";
639
640 value = INTVAL (operands[2]);
641 if (SMALL_INTVAL (value))
642 return "or %0,%1,%2";
643 else if ((value & 0xffff) == 0)
644 return "or.u %0,%1,%X2";
645 else if (integer_ok_for_set (value))
646 return "set %0,%1,%s2";
647 else
648 return "or.u %0,%1,%X2\n\tor %0,%0,%x2";
649 }
650
651 /* Emit the instructions for doing an XOR. */
652
653 const char *
output_xor(rtx operands[])654 output_xor (rtx operands[])
655 {
656 unsigned int value;
657
658 if (REG_P (operands[2]))
659 return "xor %0,%1,%2";
660
661 value = INTVAL (operands[2]);
662 if (SMALL_INTVAL (value))
663 return "xor %0,%1,%2";
664 else if ((value & 0xffff) == 0)
665 return "xor.u %0,%1,%X2";
666 else
667 return "xor.u %0,%1,%X2\n\txor %0,%0,%x2";
668 }
669
670 /* Output a call. Normally this is just bsr or jsr, but this also deals with
671 accomplishing a branch after the call by incrementing r1.
672
673 It would seem the same idea could be used to tail call, but in this case,
674 the epilogue will be non-null. */
675
676 const char *
output_call(rtx operands[],rtx addr)677 output_call (rtx operands[], rtx addr)
678 {
679 operands[0] = addr;
680 if (final_sequence)
681 {
682 rtx jump;
683 rtx seq_insn;
684
685 /* This can be generalized, but there is currently no need. */
686 gcc_assert (XVECLEN (final_sequence, 0) == 2);
687
688 /* The address of interior insns is not computed, so use the sequence. */
689 seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
690 jump = XVECEXP (final_sequence, 0, 1);
691 if (GET_CODE (jump) == JUMP_INSN)
692 {
693 const char *last;
694 rtx dest = XEXP (SET_SRC (PATTERN (jump)), 0);
695 int delta = 4 * (INSN_ADDRESSES (INSN_UID (dest))
696 - INSN_ADDRESSES (INSN_UID (seq_insn))
697 - 2);
698
699 /* Delete the jump. */
700 PUT_CODE (jump, NOTE);
701 NOTE_LINE_NUMBER (jump) = NOTE_INSN_DELETED;
702 NOTE_SOURCE_FILE (jump) = 0;
703
704 /* We only do this optimization if -O2, modifying the value of
705 r1 in the delay slot confuses debuggers and profilers on some
706 systems.
707
708 If we loose, we must use the non-delay form. This is unlikely
709 to ever happen. If it becomes a problem, claim that a call
710 has two delay slots and only the second can be filled with
711 a jump.
712
713 The 88110 can lose when a jsr.n r1 is issued and a page fault
714 occurs accessing the delay slot. So don't use jsr.n form when
715 jumping thru r1.
716 */
717 if (optimize < 2
718 || ! ADD_INTVAL (delta)
719 || (REG_P (addr) && REGNO (addr) == 1))
720 {
721 operands[1] = dest;
722 return (REG_P (addr)
723 ? "jsr %0\n\tbr %l1"
724 : (flag_pic
725 ? "bsr %0#plt\n\tbr %l1"
726 : "bsr %0\n\tbr %l1"));
727 }
728
729 /* Output the short branch form. */
730 output_asm_insn ((REG_P (addr)
731 ? "jsr.n %0"
732 : (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")),
733 operands);
734
735 last = (delta < 0
736 ? "subu %#r1,%#r1,.-%l0+4"
737 : "addu %#r1,%#r1,%l0-.-4");
738 operands[0] = dest;
739
740 return last;
741 }
742 }
743 return (REG_P (addr)
744 ? "jsr%. %0"
745 : (flag_pic ? "bsr%. %0#plt" : "bsr%. %0"));
746 }
747
748 /* Return truth value of the statement that this conditional branch is likely
749 to fall through. CONDITION, is the condition that JUMP_INSN is testing. */
750
751 bool
mostly_false_jump(rtx jump_insn,rtx condition)752 mostly_false_jump (rtx jump_insn, rtx condition)
753 {
754 rtx target_label = JUMP_LABEL (jump_insn);
755 rtx insnt, insnj;
756
757 /* Much of this isn't computed unless we're optimizing. */
758 if (optimize == 0)
759 return false;
760
761 /* Determine if one path or the other leads to a return. */
762 for (insnt = NEXT_INSN (target_label);
763 insnt;
764 insnt = NEXT_INSN (insnt))
765 {
766 if (GET_CODE (insnt) == JUMP_INSN)
767 break;
768 else if (GET_CODE (insnt) == INSN
769 && GET_CODE (PATTERN (insnt)) == SEQUENCE
770 && GET_CODE (XVECEXP (PATTERN (insnt), 0, 0)) == JUMP_INSN)
771 {
772 insnt = XVECEXP (PATTERN (insnt), 0, 0);
773 break;
774 }
775 }
776 if (insnt
777 && (GET_CODE (PATTERN (insnt)) == RETURN
778 || (GET_CODE (PATTERN (insnt)) == SET
779 && GET_CODE (SET_SRC (PATTERN (insnt))) == REG
780 && REGNO (SET_SRC (PATTERN (insnt))) == 1)))
781 insnt = NULL_RTX;
782
783 for (insnj = NEXT_INSN (jump_insn);
784 insnj;
785 insnj = NEXT_INSN (insnj))
786 {
787 if (GET_CODE (insnj) == JUMP_INSN)
788 break;
789 else if (GET_CODE (insnj) == INSN
790 && GET_CODE (PATTERN (insnj)) == SEQUENCE
791 && GET_CODE (XVECEXP (PATTERN (insnj), 0, 0)) == JUMP_INSN)
792 {
793 insnj = XVECEXP (PATTERN (insnj), 0, 0);
794 break;
795 }
796 }
797 if (insnj
798 && (GET_CODE (PATTERN (insnj)) == RETURN
799 || (GET_CODE (PATTERN (insnj)) == SET
800 && GET_CODE (SET_SRC (PATTERN (insnj))) == REG
801 && REGNO (SET_SRC (PATTERN (insnj))) == 1)))
802 insnj = NULL_RTX;
803
804 /* Predict to not return. */
805 if ((insnt == NULL_RTX) != (insnj == NULL_RTX))
806 return (insnt == NULL_RTX);
807
808 /* Predict loops to loop. */
809 for (insnt = PREV_INSN (target_label);
810 insnt && GET_CODE (insnt) == NOTE;
811 insnt = PREV_INSN (insnt))
812 if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_END)
813 return true;
814 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_BEG)
815 return false;
816
817 /* Predict backward branches usually take. */
818 if (final_sequence)
819 insnj = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
820 else
821 insnj = jump_insn;
822 if (INSN_ADDRESSES (INSN_UID (insnj))
823 > INSN_ADDRESSES (INSN_UID (target_label)))
824 return false;
825
826 /* EQ tests are usually false and NE tests are usually true. Also,
827 most quantities are positive, so we can make the appropriate guesses
828 about signed comparisons against zero. Consider unsigned comparisons
829 to be a range check and assume quantities to be in range. */
830 switch (GET_CODE (condition))
831 {
832 case CONST_INT:
833 /* Unconditional branch. */
834 return false;
835 case EQ:
836 return true;
837 case NE:
838 return false;
839 case LE:
840 case LT:
841 case GEU:
842 case GTU: /* Must get casesi right at least. */
843 if (XEXP (condition, 1) == const0_rtx)
844 return true;
845 break;
846 case GE:
847 case GT:
848 case LEU:
849 case LTU:
850 if (XEXP (condition, 1) == const0_rtx)
851 return false;
852 break;
853 default:
854 break;
855 }
856
857 return false;
858 }
859
860 /* Return true if the operand is a power of two and is a floating
861 point type (to optimize division by power of two into multiplication). */
862
863 bool
real_power_of_2_operand(rtx op)864 real_power_of_2_operand (rtx op)
865 {
866 REAL_VALUE_TYPE d;
867 union {
868 long l[2];
869 struct { /* IEEE double precision format */
870 unsigned sign : 1;
871 unsigned exponent : 11;
872 unsigned mantissa1 : 20;
873 unsigned mantissa2;
874 } s;
875 struct { /* IEEE double format to quick check */
876 unsigned sign : 1; /* if it fits in a float */
877 unsigned exponent1 : 4;
878 unsigned exponent2 : 7;
879 unsigned mantissa1 : 20;
880 unsigned mantissa2;
881 } s2;
882 } u;
883
884 if (GET_MODE (op) != DFmode && GET_MODE (op) != SFmode)
885 return false;
886
887 if (GET_CODE (op) != CONST_DOUBLE)
888 return false;
889
890 REAL_VALUE_FROM_CONST_DOUBLE (d, op);
891 REAL_VALUE_TO_TARGET_DOUBLE (d, u.l);
892
893 if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0 /* not a power of two */
894 || u.s.exponent == 0 /* constant 0.0 */
895 || u.s.exponent == 0x7ff /* NaN */
896 || (u.s2.exponent1 != 0x8 && u.s2.exponent1 != 0x7))
897 return false; /* const won't fit in float */
898
899 return true;
900 }
901
902 /* Make OP legitimate for mode MODE. Currently this only deals with DFmode
903 operands, putting them in registers and making CONST_DOUBLE values
904 SFmode where possible. */
905
906 struct rtx_def *
legitimize_operand(rtx op,enum machine_mode mode)907 legitimize_operand (rtx op, enum machine_mode mode)
908 {
909 rtx temp;
910 REAL_VALUE_TYPE d;
911 union {
912 long l[2];
913 struct { /* IEEE double precision format */
914 unsigned sign : 1;
915 unsigned exponent : 11;
916 unsigned mantissa1 : 20;
917 unsigned mantissa2;
918 } s;
919 struct { /* IEEE double format to quick check */
920 unsigned sign : 1; /* if it fits in a float */
921 unsigned exponent1 : 4;
922 unsigned exponent2 : 7;
923 unsigned mantissa1 : 20;
924 unsigned mantissa2;
925 } s2;
926 } u;
927
928 if (GET_CODE (op) == REG || mode != DFmode)
929 return op;
930
931 if (GET_CODE (op) == CONST_DOUBLE)
932 {
933 REAL_VALUE_FROM_CONST_DOUBLE (d, op);
934 REAL_VALUE_TO_TARGET_DOUBLE (d, u.l);
935 if (u.s.exponent != 0x7ff /* NaN */
936 && u.s.mantissa2 == 0 /* Mantissa fits */
937 && (u.s2.exponent1 == 0x8 || u.s2.exponent1 == 0x7) /* Exponent fits */
938 && (temp = simplify_unary_operation (FLOAT_TRUNCATE, SFmode,
939 op, mode)) != 0)
940 return gen_rtx_FLOAT_EXTEND (mode, force_reg (SFmode, temp));
941 }
942 else if (register_operand (op, mode))
943 return op;
944
945 return force_reg (mode, op);
946 }
947
948 /* Returns true if OP is either a symbol reference or a sum of a symbol
949 reference and a constant. */
950
951 bool
symbolic_address_p(rtx op)952 symbolic_address_p (rtx op)
953 {
954 switch (GET_CODE (op))
955 {
956 case SYMBOL_REF:
957 case LABEL_REF:
958 return true;
959
960 case CONST:
961 op = XEXP (op, 0);
962 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
963 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
964 && GET_CODE (XEXP (op, 1)) == CONST_INT);
965
966 default:
967 return false;
968 }
969 }
970
971 /* Nonzero if this is a bitmask filling the bottom bits, for optimizing and +
972 shift left combinations into a single mak instruction. */
973
974 bool
mak_mask_p(int value)975 mak_mask_p (int value)
976 {
977 return (value && POWER_OF_2_or_0 (value + 1));
978 }
979
980 /* Output to FILE the start of the assembler file. */
981
982 static void
m88k_output_file_start(void)983 m88k_output_file_start (void)
984 {
985 if (TARGET_88110)
986 fprintf (asm_out_file, "%s\n", REQUIRES_88110_ASM_OP);
987
988 default_file_start ();
989 }
990
991 /* Generate the assembly code for function entry.
992
993 The prologue is responsible for setting up the stack frame,
994 initializing the frame pointer register, saving registers that must be
995 saved, and allocating SIZE additional bytes of storage for the
996 local variables. SIZE is an integer. FILE is a stdio
997 stream to which the assembler code should be output.
998
999 The label for the beginning of the function need not be output by this
1000 macro. That has already been done when the macro is run.
1001
1002 To determine which registers to save, the macro can refer to the array
1003 `regs_ever_live': element R is nonzero if hard register
1004 R is used anywhere within the function. This implies the
1005 function prologue should save register R, but not if it is one
1006 of the call-used registers.
1007
1008 On machines where functions may or may not have frame-pointers, the
1009 function entry code must vary accordingly; it must set up the frame
1010 pointer if one is wanted, and not otherwise. To determine whether a
1011 frame pointer is in wanted, the macro can refer to the variable
1012 `frame_pointer_needed'. The variable's value will be 1 at run
1013 time in a function that needs a frame pointer.
1014
1015 On machines where an argument may be passed partly in registers and
1016 partly in memory, this macro must examine the variable
1017 `current_function_pretend_args_size', and allocate that many bytes
1018 of uninitialized space on the stack just underneath the first argument
1019 arriving on the stack. (This may not be at the very end of the stack,
1020 if the calling sequence has pushed anything else since pushing the stack
1021 arguments. But usually, on such machines, nothing else has been pushed
1022 yet, because the function prologue itself does all the pushing.)
1023
1024 If `ACCUMULATE_OUTGOING_ARGS' is defined, the variable
1025 `current_function_outgoing_args_size' contains the size in bytes
1026 required for the outgoing arguments. This macro must add that
1027 amount of uninitialized space to very bottom of the stack.
1028
1029 The stack frame we use looks like this:
1030
1031 caller callee
1032 |==============================================|
1033 | caller's frame |
1034 |==============================================|
1035 | [caller's outgoing memory arguments] |
1036 sp -> |==============================================| <- ap
1037 | [local variable space] |
1038 |----------------------------------------------|
1039 | [return address (r1)] |
1040 |----------------------------------------------|
1041 | [previous frame pointer (r30)] |
1042 |==============================================| <- fp
1043 | [preserved registers (r25..r14)] |
1044 |----------------------------------------------|
1045 | [preserved registers (x29..x22)] |
1046 |==============================================|
1047 | [dynamically allocated space (alloca)] |
1048 |==============================================|
1049 | [callee's outgoing memory arguments] |
1050 |==============================================| <- sp
1051
1052 Notes:
1053
1054 r1 and r30 must be saved if debugging.
1055
1056 fp (if present) is located two words down from the local
1057 variable space.
1058 */
1059
1060 static rtx emit_add (rtx, rtx, int);
1061 static void preserve_registers (int, int);
1062 static void emit_ldst (int, int, enum machine_mode, int);
1063
1064 static int nregs;
1065 static int nxregs;
1066 static char save_regs[FIRST_PSEUDO_REGISTER];
1067 static int frame_laid_out;
1068 static int frame_size;
1069
1070 #define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
1071 #define ROUND_CALL_BLOCK_SIZE(BYTES) \
1072 (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
1073
1074 /* Establish the position of the FP relative to the SP. This is done
1075 either during output_function_prologue() or by
1076 INITIAL_ELIMINATION_OFFSET. */
1077
1078 void
m88k_layout_frame(void)1079 m88k_layout_frame (void)
1080 {
1081 int regno, sp_size;
1082
1083 if (frame_laid_out && reload_completed)
1084 return;
1085
1086 frame_laid_out = 1;
1087
1088 memset ((char *) &save_regs[0], 0, sizeof (save_regs));
1089 sp_size = nregs = nxregs = 0;
1090 frame_size = get_frame_size ();
1091
1092 /* Profiling requires a stack frame. */
1093 if (current_function_profile)
1094 frame_pointer_needed = 1;
1095
1096 /* If we are producing debug information, store r1 and r30 where the
1097 debugger wants to find them (r30 at r30+0, r1 at r30+4). Space has
1098 already been reserved for r1/r30 in STARTING_FRAME_OFFSET. */
1099 if (write_symbols != NO_DEBUG)
1100 save_regs[1] = 1;
1101
1102 /* If we are producing PIC, save the addressing base register and r1. */
1103 if (flag_pic && current_function_uses_pic_offset_table)
1104 {
1105 save_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
1106 nregs++;
1107 }
1108
1109 /* If a frame is requested, save the previous FP, and the return
1110 address (r1), so that a traceback can be done without using tdesc
1111 information. Otherwise, simply save the FP if it is used as
1112 a preserve register. */
1113 if (frame_pointer_needed)
1114 save_regs[FRAME_POINTER_REGNUM] = save_regs[1] = 1;
1115 else
1116 {
1117 if (regs_ever_live[FRAME_POINTER_REGNUM])
1118 save_regs[FRAME_POINTER_REGNUM] = 1;
1119 /* If there is a call, r1 needs to be saved as well. */
1120 if (regs_ever_live[1])
1121 save_regs[1] = 1;
1122 }
1123
1124 /* Figure out which extended register(s) needs to be saved. */
1125 for (regno = FIRST_EXTENDED_REGISTER + 1; regno < FIRST_PSEUDO_REGISTER;
1126 regno++)
1127 if (regs_ever_live[regno] && ! call_used_regs[regno])
1128 {
1129 save_regs[regno] = 1;
1130 nxregs++;
1131 }
1132
1133 /* Figure out which normal register(s) needs to be saved. */
1134 for (regno = 2; regno < FRAME_POINTER_REGNUM; regno++)
1135 if (regs_ever_live[regno] && ! call_used_regs[regno])
1136 {
1137 save_regs[regno] = 1;
1138 nregs++;
1139 }
1140
1141 /* Achieve greatest use of double memory ops. Either we end up saving
1142 r30 or we use that slot to align the registers we do save. */
1143 if (nregs >= 2 && save_regs[1] && !save_regs[FRAME_POINTER_REGNUM])
1144 sp_size += 4;
1145
1146 nregs += save_regs[1] + save_regs[FRAME_POINTER_REGNUM];
1147 /* if we need to align extended registers, add a word */
1148 if (nxregs > 0 && (nregs & 1) != 0)
1149 sp_size +=4;
1150 sp_size += 4 * nregs;
1151 sp_size += 8 * nxregs;
1152 sp_size += current_function_outgoing_args_size;
1153
1154 /* The first two saved registers are placed above the new frame pointer
1155 if any. In the only case this matters, they are r1 and r30. */
1156 if (frame_pointer_needed || sp_size)
1157 m88k_fp_offset = ROUND_CALL_BLOCK_SIZE (sp_size - STARTING_FRAME_OFFSET);
1158 else
1159 m88k_fp_offset = -STARTING_FRAME_OFFSET;
1160 m88k_stack_size = m88k_fp_offset + STARTING_FRAME_OFFSET;
1161
1162 /* First, combine m88k_stack_size and size. If m88k_stack_size is
1163 nonzero, align the frame size to 8 mod 16; otherwise align the
1164 frame size to 0 mod 16. (If stacks are 8 byte aligned, this ends
1165 up as a NOP. */
1166 {
1167 int need
1168 = ((m88k_stack_size ? STACK_UNIT_BOUNDARY - STARTING_FRAME_OFFSET : 0)
1169 - (frame_size % STACK_UNIT_BOUNDARY));
1170 if (need < 0)
1171 need += STACK_UNIT_BOUNDARY;
1172 m88k_stack_size
1173 = ROUND_CALL_BLOCK_SIZE (m88k_stack_size + frame_size + need
1174 + current_function_pretend_args_size);
1175 }
1176 }
1177
1178 /* Return true if this function is known to have a null prologue. */
1179
1180 bool
null_prologue(void)1181 null_prologue (void)
1182 {
1183 if (! reload_completed)
1184 return false;
1185 m88k_layout_frame ();
1186 return (! frame_pointer_needed
1187 && nregs == 0
1188 && nxregs == 0
1189 && m88k_stack_size == 0);
1190 }
1191
1192 static void
m88k_maybe_dead(rtx insn)1193 m88k_maybe_dead (rtx insn)
1194 {
1195 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
1196 const0_rtx,
1197 REG_NOTES (insn));
1198 }
1199
1200 void
m88k_expand_prologue(void)1201 m88k_expand_prologue (void)
1202 {
1203 rtx insn;
1204
1205 m88k_layout_frame ();
1206
1207 if (warn_stack_larger_than && m88k_stack_size > stack_larger_than_size)
1208 warning (0, "stack usage is %d bytes", m88k_stack_size);
1209
1210 if (m88k_stack_size)
1211 {
1212 insn = emit_add (stack_pointer_rtx, stack_pointer_rtx, -m88k_stack_size);
1213 RTX_FRAME_RELATED_P (insn) = 1;
1214
1215 /* If the stack pointer adjustment has required a temporary register,
1216 tell the DWARF code how to understand this sequence. */
1217 if (! ADD_INTVAL (m88k_stack_size))
1218 REG_NOTES (insn)
1219 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
1220 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
1221 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
1222 GEN_INT (-m88k_stack_size))),
1223 REG_NOTES(insn));
1224 }
1225
1226 if (nregs || nxregs)
1227 preserve_registers (m88k_fp_offset + 4, 1);
1228
1229 if (frame_pointer_needed)
1230 {
1231 /* Be sure to emit this instruction after all register saves, DWARF
1232 information depends on this. */
1233 emit_insn (gen_blockage ());
1234 insn = emit_add (frame_pointer_rtx, stack_pointer_rtx, m88k_fp_offset);
1235 RTX_FRAME_RELATED_P (insn) = 1;
1236 }
1237
1238 if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM])
1239 {
1240 rtx return_reg = gen_rtx_REG (SImode, 1);
1241 rtx label = gen_label_rtx ();
1242
1243 m88k_maybe_dead (emit_insn (gen_locate1 (pic_offset_table_rtx, label)));
1244 m88k_maybe_dead (emit_insn (gen_locate2 (pic_offset_table_rtx, label)));
1245 m88k_maybe_dead (emit_insn (gen_addsi3 (pic_offset_table_rtx,
1246 pic_offset_table_rtx,
1247 return_reg)));
1248 }
1249 if (current_function_profile)
1250 emit_insn (gen_blockage ());
1251 }
1252
1253 /* This function generates the assembly code for function exit,
1254 on machines that need it.
1255
1256 The function epilogue should not depend on the current stack pointer!
1257 It should use the frame pointer only, if there is a frame pointer.
1258 This is mandatory because of alloca; we also take advantage of it to
1259 omit stack adjustments before returning. */
1260
1261 static void
m88k_output_function_epilogue(FILE * stream,HOST_WIDE_INT size ATTRIBUTE_UNUSED)1262 m88k_output_function_epilogue (FILE *stream,
1263 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
1264 {
1265 frame_laid_out = 0;
1266 }
1267
1268 void
m88k_expand_epilogue(void)1269 m88k_expand_epilogue (void)
1270 {
1271 if (frame_pointer_needed)
1272 {
1273 emit_insn (gen_blockage ());
1274 emit_add (stack_pointer_rtx, frame_pointer_rtx, -m88k_fp_offset);
1275 }
1276
1277 if (nregs || nxregs)
1278 preserve_registers (m88k_fp_offset + 4, 0);
1279
1280 emit_insn (gen_blockage ());
1281
1282 if (m88k_stack_size)
1283 {
1284 emit_add (stack_pointer_rtx, stack_pointer_rtx, m88k_stack_size);
1285 }
1286
1287 emit_insn (gen_indirect_jump (INCOMING_RETURN_ADDR_RTX));
1288
1289 emit_insn (gen_blockage ());
1290 }
1291
1292 /* Emit insns to set DSTREG to SRCREG + AMOUNT during the prologue or
1293 epilogue. */
1294
1295 static rtx
emit_add(rtx dstreg,rtx srcreg,int amount)1296 emit_add (rtx dstreg, rtx srcreg, int amount)
1297 {
1298 rtx incr = GEN_INT (abs (amount));
1299
1300 if (! ADD_INTVAL (amount))
1301 {
1302 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
1303 emit_move_insn (temp, incr);
1304 incr = temp;
1305 }
1306 return emit_insn ((amount < 0 ? gen_subsi3 : gen_addsi3) (dstreg, srcreg,
1307 incr));
1308 }
1309
1310 /* Save/restore the preserve registers. base is the highest offset from
1311 r31 at which a register is stored. store_p is true if stores are to
1312 be done; otherwise loads. */
1313
1314 static void
preserve_registers(int base,int store_p)1315 preserve_registers (int base, int store_p)
1316 {
1317 int regno, offset;
1318 struct mem_op {
1319 int regno;
1320 int nregs;
1321 int offset;
1322 } mem_op[FIRST_PSEUDO_REGISTER];
1323 struct mem_op *mo_ptr = mem_op;
1324
1325 /* The 88open OCS mandates that preserved registers be stored in
1326 increasing order. For compatibility with current practice,
1327 the order is r1, r30, then the preserve registers. */
1328
1329 offset = base;
1330 if (save_regs[1])
1331 {
1332 /* An extra word is given in this case to make best use of double
1333 memory ops. */
1334 if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM])
1335 offset -= 4;
1336 /* Do not reload r1 in the epilogue unless really necessary */
1337 if (store_p || regs_ever_live[1]
1338 || (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM]))
1339 emit_ldst (store_p, 1, SImode, offset);
1340 offset -= 4;
1341 base = offset;
1342 }
1343
1344 /* Walk the registers to save recording all single memory operations. */
1345 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
1346 if (save_regs[regno])
1347 {
1348 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
1349 {
1350 mo_ptr->nregs = 1;
1351 mo_ptr->regno = regno;
1352 mo_ptr->offset = offset;
1353 mo_ptr++;
1354 offset -= 4;
1355 }
1356 else
1357 {
1358 regno--;
1359 offset -= 2*4;
1360 }
1361 }
1362
1363 /* Walk the registers to save recording all double memory operations.
1364 This avoids a delay in the epilogue (ld.d/ld). */
1365 offset = base;
1366 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
1367 if (save_regs[regno])
1368 {
1369 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
1370 {
1371 offset -= 4;
1372 }
1373 else
1374 {
1375 mo_ptr->nregs = 2;
1376 mo_ptr->regno = regno-1;
1377 mo_ptr->offset = offset-4;
1378 mo_ptr++;
1379 regno--;
1380 offset -= 2*4;
1381 }
1382 }
1383
1384 /* Walk the extended registers to record all memory operations. */
1385 /* Be sure the offset is double word aligned. */
1386 offset = (offset - 1) & ~7;
1387 for (regno = FIRST_PSEUDO_REGISTER - 1; regno > FIRST_EXTENDED_REGISTER;
1388 regno--)
1389 if (save_regs[regno])
1390 {
1391 mo_ptr->nregs = 2;
1392 mo_ptr->regno = regno;
1393 mo_ptr->offset = offset;
1394 mo_ptr++;
1395 offset -= 2*4;
1396 }
1397
1398 mo_ptr->regno = 0;
1399
1400 /* Output the memory operations. */
1401 for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++)
1402 {
1403 if (mo_ptr->nregs)
1404 emit_ldst (store_p, mo_ptr->regno,
1405 (mo_ptr->nregs > 1 ? DImode : SImode),
1406 mo_ptr->offset);
1407 }
1408 }
1409
1410 static void
emit_ldst(int store_p,int regno,enum machine_mode mode,int offset)1411 emit_ldst (int store_p, int regno, enum machine_mode mode, int offset)
1412 {
1413 rtx reg = gen_rtx_REG (mode, regno);
1414 rtx mem;
1415 rtx insn;
1416
1417 if (SMALL_INTVAL (offset))
1418 {
1419 mem = gen_rtx_MEM (mode, plus_constant (stack_pointer_rtx, offset));
1420 }
1421 else
1422 {
1423 /* offset is too large for immediate index must use register */
1424
1425 rtx disp = GEN_INT (offset);
1426 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
1427 rtx regi = gen_rtx_PLUS (SImode, stack_pointer_rtx, temp);
1428
1429 emit_move_insn (temp, disp);
1430 mem = gen_rtx_MEM (mode, regi);
1431 }
1432
1433 if (store_p)
1434 {
1435 insn = emit_move_insn (mem, reg);
1436 RTX_FRAME_RELATED_P (insn) = 1;
1437 }
1438 else
1439 emit_move_insn (reg, mem);
1440 }
1441
1442 /* Convert the address expression REG to a CFA offset. */
1443
1444 int
m88k_debugger_offset(rtx reg,int offset)1445 m88k_debugger_offset (rtx reg, int offset)
1446 {
1447 if (GET_CODE (reg) == PLUS)
1448 {
1449 offset = INTVAL (XEXP (reg, 1));
1450 reg = XEXP (reg, 0);
1451 }
1452
1453 /* Put the offset in terms of the CFA (arg pointer). */
1454 if (reg == frame_pointer_rtx)
1455 offset += m88k_fp_offset - m88k_stack_size;
1456 else if (reg == stack_pointer_rtx)
1457 offset -= m88k_stack_size;
1458 else if (reg != arg_pointer_rtx)
1459 return 0;
1460
1461 return offset;
1462 }
1463
1464 /* Output assembler code to FILE to increment profiler label # LABELNO
1465 for profiling a function entry. NAME is the mcount function name
1466 (varies). */
1467
1468 void
output_function_profiler(FILE * file,int labelno,const char * name)1469 output_function_profiler (FILE *file, int labelno, const char *name)
1470 {
1471 char label[256];
1472
1473 /* Remember to update FUNCTION_PROFILER_LENGTH. */
1474
1475 asm_fprintf (file, "\tsubu\t %R%s,%R%s,32\n", reg_names[31], reg_names[31]);
1476 asm_fprintf (file, "\tst.d\t %R%s,%R%s,0\n", reg_names[2], reg_names[31]);
1477 asm_fprintf (file, "\tst.d\t %R%s,%R%s,8\n", reg_names[4], reg_names[31]);
1478 asm_fprintf (file, "\tst.d\t %R%s,%R%s,16\n", reg_names[6], reg_names[31]);
1479 asm_fprintf (file, "\tst.d\t %R%s,%R%s,24\n", reg_names[8], reg_names[31]);
1480
1481 ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno);
1482 if (flag_pic == 2)
1483 {
1484 asm_fprintf (file, "\tor.u\t %R%s,%R%s,%Rhi16(%s#got_rel)\n",
1485 reg_names[2], reg_names[0], &label[1]);
1486 asm_fprintf (file, "\tor\t %R%s,%R%s,%Rlo16(%s#got_rel)\n",
1487 reg_names[2], reg_names[2], &label[1]);
1488 asm_fprintf (file, "\tbsr.n\t %s#plt\n", name);
1489 asm_fprintf (file, "\t ld\t %R%s,%R%s,%R%s\n", reg_names[2],
1490 reg_names[PIC_OFFSET_TABLE_REGNUM], reg_names[2]);
1491 }
1492 else if (flag_pic)
1493 {
1494 asm_fprintf (file, "\tbsr.n\t %s#plt\n", name);
1495 asm_fprintf (file, "\t ld\t %R%s,%R%s,%s#got_rel\n", reg_names[2],
1496 reg_names[PIC_OFFSET_TABLE_REGNUM], &label[1]);
1497 }
1498 else
1499 {
1500 asm_fprintf (file, "\tor.u\t %R%s,%R%s,%Rhi16(%s)\n",
1501 reg_names[2], reg_names[0], &label[1]);
1502 asm_fprintf (file, "\tbsr.n\t %s\n", name);
1503 asm_fprintf (file, "\t or\t %R%s,%R%s,%Rlo16(%s)\n",
1504 reg_names[2], reg_names[2], &label[1]);
1505 }
1506
1507 asm_fprintf (file, "\tld.d\t %R%s,%R%s,0\n", reg_names[2], reg_names[31]);
1508 asm_fprintf (file, "\tld.d\t %R%s,%R%s,8\n", reg_names[4], reg_names[31]);
1509 asm_fprintf (file, "\tld.d\t %R%s,%R%s,16\n", reg_names[6], reg_names[31]);
1510 asm_fprintf (file, "\tld.d\t %R%s,%R%s,24\n", reg_names[8], reg_names[31]);
1511 asm_fprintf (file, "\taddu\t %R%s,%R%s,32\n", reg_names[31], reg_names[31]);
1512 }
1513
1514 /* Determine whether a function argument is passed in a register, and
1515 which register.
1516
1517 The arguments are CUM, which summarizes all the previous
1518 arguments; MODE, the machine mode of the argument; TYPE,
1519 the data type of the argument as a tree node or 0 if that is not known
1520 (which happens for C support library functions); and NAMED,
1521 which is 1 for an ordinary argument and 0 for nameless arguments that
1522 correspond to `...' in the called function's prototype.
1523
1524 The value of the expression should either be a `reg' RTX for the
1525 hard register in which to pass the argument, or zero to pass the
1526 argument on the stack.
1527
1528 On the m88000 the first eight words of args are normally in registers
1529 and the rest are pushed. Double precision floating point must be
1530 double word aligned (and if in a register, starting on an even
1531 register). Structures and unions which are not 4 byte, and word
1532 aligned are passed in memory rather than registers, even if they
1533 would fit completely in the registers under OCS rules.
1534
1535 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
1536 For structures that are passed in memory, but could have been
1537 passed in registers, we first load the structure into the
1538 register, and then when the last argument is passed, we store
1539 the registers into the stack locations. This fixes some bugs
1540 where GCC did not expect to have register arguments, followed
1541 by stack arguments, followed by register arguments. */
1542
1543 struct rtx_def *
m88k_function_arg(CUMULATIVE_ARGS args_so_far,enum machine_mode mode,tree type,int named ATTRIBUTE_UNUSED)1544 m88k_function_arg (CUMULATIVE_ARGS args_so_far, enum machine_mode mode,
1545 tree type, int named ATTRIBUTE_UNUSED)
1546 {
1547 int bytes, words;
1548
1549 /* undo putting struct in register */
1550 if (type != NULL_TREE && AGGREGATE_TYPE_P (type))
1551 mode = BLKmode;
1552
1553 /* m88k_function_arg argument `type' is NULL for BLKmode. */
1554 gcc_assert (type != NULL_TREE || mode != BLKmode);
1555
1556 bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
1557
1558 /* Variable-sized types get passed by reference, which can be passed
1559 in registers. */
1560 if (bytes < 0)
1561 {
1562 if (args_so_far > 8 - (POINTER_SIZE / BITS_PER_WORD))
1563 return NULL_RTX;
1564
1565 return gen_rtx_REG (Pmode, 2 + args_so_far);
1566 }
1567
1568 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1569
1570 if ((args_so_far & 1) != 0
1571 && (mode == DImode || mode == DFmode
1572 || (type != NULL_TREE && TYPE_ALIGN (type) > BITS_PER_WORD)))
1573 args_so_far++;
1574
1575 if (args_so_far + words > 8)
1576 return NULL_RTX; /* args have exhausted registers */
1577
1578 else if (mode == BLKmode
1579 && (TYPE_ALIGN (type) != BITS_PER_WORD || bytes != UNITS_PER_WORD))
1580 return NULL_RTX;
1581
1582 return gen_rtx_REG (((mode == BLKmode) ? TYPE_MODE (type) : mode),
1583 2 + args_so_far);
1584 }
1585
1586 /* Update the summarizer variable CUM to advance past an argument in
1587 the argument list. The values MODE, TYPE and NAMED describe that
1588 argument. Once this is done, the variable CUM is suitable for
1589 analyzing the *following* argument with `FUNCTION_ARG', etc. (TYPE
1590 is null for libcalls where that information may not be available.) */
1591 void
m88k_function_arg_advance(CUMULATIVE_ARGS * args_so_far,enum machine_mode mode,tree type,int named ATTRIBUTE_UNUSED)1592 m88k_function_arg_advance (CUMULATIVE_ARGS *args_so_far, enum machine_mode mode,
1593 tree type, int named ATTRIBUTE_UNUSED)
1594 {
1595 int bytes, words;
1596 int asf;
1597
1598 if (type != NULL_TREE && AGGREGATE_TYPE_P (type))
1599 mode = BLKmode;
1600
1601 bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
1602 asf = *args_so_far;
1603
1604 /* Variable-sized types get passed by reference, which can be passed
1605 in registers. */
1606 if (bytes < 0)
1607 {
1608 if (asf <= 8 - (POINTER_SIZE / BITS_PER_WORD))
1609 *args_so_far += POINTER_SIZE / BITS_PER_WORD;
1610
1611 return;
1612 }
1613
1614 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1615
1616 /* Struct and unions which are not exactly the size of a register are to be
1617 passed on stack. */
1618 if (mode == BLKmode
1619 && (TYPE_ALIGN (type) != BITS_PER_WORD || bytes != UNITS_PER_WORD))
1620 return;
1621
1622 /* Align arguments requiring more than word alignment to a double-word
1623 boundary (or an even register number if the argument will get passed
1624 in registers). */
1625 if ((asf & 1) != 0
1626 && (mode == DImode || mode == DFmode
1627 || (type != NULL_TREE && TYPE_ALIGN (type) > BITS_PER_WORD)))
1628 asf++;
1629
1630 if (asf + words > 8)
1631 return;
1632
1633 (*args_so_far) = asf + words;
1634 }
1635
1636 /* A C expression that indicates when an argument must be passed by
1637 reference. If nonzero for an argument, a copy of that argument is
1638 made in memory and a pointer to the argument is passed instead of
1639 the argument itself. The pointer is passed in whatever way is
1640 appropriate for passing a pointer to that type.
1641
1642 On m88k, only variable sized types are passed by reference. */
1643
1644 static bool
m88k_pass_by_reference(CUMULATIVE_ARGS * cum ATTRIBUTE_UNUSED,enum machine_mode mode ATTRIBUTE_UNUSED,tree type,bool named ATTRIBUTE_UNUSED)1645 m88k_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1646 enum machine_mode mode ATTRIBUTE_UNUSED,
1647 tree type, bool named ATTRIBUTE_UNUSED)
1648 {
1649 return type != NULL_TREE && int_size_in_bytes (type) < 0;
1650 }
1651
1652 /* Disable the promotion of some structures and unions to registers.
1653 Note that this matches FUNCTION_ARG behaviour. */
1654 static bool
m88k_return_in_memory(tree type,tree fndecl ATTRIBUTE_UNUSED)1655 m88k_return_in_memory (tree type, tree fndecl ATTRIBUTE_UNUSED)
1656 {
1657 switch (TYPE_MODE (type))
1658 {
1659 case BLKmode:
1660 return true;
1661 default:
1662 if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE)
1663 && (TYPE_ALIGN (type) != BITS_PER_WORD
1664 || GET_MODE_SIZE (TYPE_MODE (type)) != UNITS_PER_WORD))
1665 return true;
1666 return false;
1667 }
1668 }
1669
1670 /* Perform any needed actions needed for a function that is receiving a
1671 variable number of arguments.
1672
1673 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1674 the preceding args and about the function being called.
1675
1676 MODE and TYPE are the mode and type of the current parameter.
1677
1678 PRETEND_SIZE is a variable that should be set to the amount of stack
1679 that must be pushed by the prolog to pretend that our caller pushed
1680 it.
1681
1682 Normally, this macro will push all remaining incoming registers on the
1683 stack and set PRETEND_SIZE to the length of the registers pushed. */
1684
1685 void
m88k_setup_incoming_varargs(CUMULATIVE_ARGS * cum,enum machine_mode mode,tree type,int * pretend_size,int no_rtl)1686 m88k_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1687 tree type, int *pretend_size, int no_rtl)
1688 {
1689 CUMULATIVE_ARGS next_cum;
1690 tree fntype;
1691 int stdarg_p;
1692 int regcnt, delta;
1693
1694 fntype = TREE_TYPE (current_function_decl);
1695 stdarg_p = (TYPE_ARG_TYPES (fntype) != NULL_TREE
1696 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1697 != void_type_node));
1698
1699 /* For varargs, we do not want to skip the dummy va_dcl argument.
1700 For stdargs, we do want to skip the last named argument. */
1701 next_cum = *cum;
1702 if (stdarg_p)
1703 m88k_function_arg_advance(&next_cum, mode, type, 1);
1704
1705 regcnt = next_cum < 8 ? 8 - next_cum : 0;
1706 delta = regcnt & 1;
1707
1708 if (! no_rtl && regcnt != 0)
1709 {
1710 rtx mem, dst;
1711 int set, regno, offs;
1712
1713 set = get_varargs_alias_set ();
1714 mem = gen_rtx_MEM (BLKmode,
1715 plus_constant (virtual_incoming_args_rtx,
1716 - (regcnt + delta) * UNITS_PER_WORD));
1717 MEM_NOTRAP_P (mem) = 1;
1718 set_mem_alias_set (mem, set);
1719
1720 /* Now store the incoming registers. */
1721 /* The following is equivalent to
1722 move_block_from_reg (2 + next_cum,
1723 adjust_address (mem, Pmode,
1724 delta * UNITS_PER_WORD),
1725 regcnt, UNITS_PER_WORD * regcnt);
1726 but using double store instruction since the stack is properly
1727 aligned. */
1728 regno = 2 + next_cum;
1729 dst = mem;
1730
1731 if (delta != 0)
1732 {
1733 dst = adjust_address (dst, Pmode, UNITS_PER_WORD);
1734 emit_move_insn (operand_subword (dst, 0, 1, BLKmode),
1735 gen_rtx_REG (SImode, regno));
1736 regno++;
1737 }
1738
1739 offs = delta;
1740 while (regno < 10)
1741 {
1742 emit_move_insn (adjust_address (dst, DImode, offs * UNITS_PER_WORD),
1743 gen_rtx_REG (DImode, regno));
1744 offs += 2;
1745 regno += 2;
1746 }
1747
1748 *pretend_size = (regcnt + delta) * UNITS_PER_WORD;
1749 }
1750 }
1751
1752 /* Define the `__builtin_va_list' type for the ABI. */
1753
1754 static tree
m88k_build_va_list(void)1755 m88k_build_va_list (void)
1756 {
1757 tree field_reg, field_stk, field_arg, int_ptr_type_node, record;
1758
1759 int_ptr_type_node = build_pointer_type (integer_type_node);
1760
1761 record = make_node (RECORD_TYPE);
1762
1763 field_arg = build_decl (FIELD_DECL, get_identifier ("__va_arg"),
1764 integer_type_node);
1765 field_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"),
1766 int_ptr_type_node);
1767 field_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),
1768 int_ptr_type_node);
1769
1770 DECL_FIELD_CONTEXT (field_arg) = record;
1771 DECL_FIELD_CONTEXT (field_stk) = record;
1772 DECL_FIELD_CONTEXT (field_reg) = record;
1773
1774 TYPE_FIELDS (record) = field_arg;
1775 TREE_CHAIN (field_arg) = field_stk;
1776 TREE_CHAIN (field_stk) = field_reg;
1777
1778 layout_type (record);
1779 return record;
1780 }
1781
1782 /* Implement `va_start' for varargs and stdarg. */
1783
1784 void
m88k_va_start(tree valist,rtx nextarg ATTRIBUTE_UNUSED)1785 m88k_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
1786 {
1787 tree field_reg, field_stk, field_arg;
1788 tree reg, stk, arg, t;
1789 tree fntype;
1790 int stdarg_p;
1791 int offset;
1792
1793 gcc_assert (CONSTANT_P (current_function_arg_offset_rtx));
1794
1795 field_arg = TYPE_FIELDS (va_list_type_node);
1796 field_stk = TREE_CHAIN (field_arg);
1797 field_reg = TREE_CHAIN (field_stk);
1798
1799 arg = build3 (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg,
1800 NULL_TREE);
1801 stk = build3 (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk,
1802 NULL_TREE);
1803 reg = build3 (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg,
1804 NULL_TREE);
1805
1806 fntype = TREE_TYPE (current_function_decl);
1807 stdarg_p = (TYPE_ARG_TYPES (fntype) != NULL_TREE
1808 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1809 != void_type_node));
1810
1811 /* Fill in the __va_arg member. */
1812 t = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg,
1813 size_int (current_function_args_info));
1814 TREE_SIDE_EFFECTS (t) = 1;
1815 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
1816
1817 /* Store the arg pointer in the __va_stk member. */
1818 offset = XINT (current_function_arg_offset_rtx, 0);
1819 if (current_function_args_info >= 8 && ! stdarg_p)
1820 offset -= UNITS_PER_WORD;
1821 t = make_tree (TREE_TYPE (stk), virtual_incoming_args_rtx);
1822 t = build2 (PLUS_EXPR, TREE_TYPE (stk), t, size_int (offset));
1823 t = build2 (MODIFY_EXPR, TREE_TYPE (stk), stk, t);
1824 TREE_SIDE_EFFECTS (t) = 1;
1825 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
1826
1827 /* Setup __va_reg */
1828 t = make_tree (TREE_TYPE (reg), virtual_incoming_args_rtx);
1829 t = build2 (PLUS_EXPR, TREE_TYPE (reg), t,
1830 build_int_cst (NULL_TREE, -8 * UNITS_PER_WORD));
1831 t = build2 (MODIFY_EXPR, TREE_TYPE (reg), reg, t);
1832 TREE_SIDE_EFFECTS (t) = 1;
1833 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
1834 }
1835
1836 /* Implement `va_arg'. */
1837
1838 tree
m88k_gimplify_va_arg(tree valist,tree type,tree * pre_p,tree * post_p)1839 m88k_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
1840 {
1841 tree field_reg, field_stk, field_arg;
1842 int size, wsize, align;
1843 bool reg_p;
1844 tree ptrtype = build_pointer_type (type);
1845 tree lab_done;
1846 tree addr;
1847 tree t;
1848
1849 if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
1850 {
1851 t = m88k_gimplify_va_arg (valist, ptrtype, pre_p, post_p);
1852 return build_va_arg_indirect_ref (t);
1853 }
1854
1855 field_arg = TYPE_FIELDS (va_list_type_node);
1856 field_stk = TREE_CHAIN (field_arg);
1857 field_reg = TREE_CHAIN (field_stk);
1858
1859 size = int_size_in_bytes (type);
1860 wsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1861 reg_p = (AGGREGATE_TYPE_P (type)
1862 ? size == UNITS_PER_WORD && TYPE_ALIGN (type) == BITS_PER_WORD
1863 : size <= 2*UNITS_PER_WORD);
1864
1865 addr = create_tmp_var (ptr_type_node, "addr");
1866 DECL_POINTER_ALIAS_SET (addr) = get_varargs_alias_set ();
1867 lab_done = NULL;
1868
1869 /* Decide if we should read from stack or regs if the argument could have
1870 been passed in registers. */
1871 if (reg_p) {
1872 tree arg, arg_align, reg;
1873 tree lab_stack;
1874 tree u;
1875
1876 lab_stack = create_artificial_label ();
1877 lab_done = create_artificial_label ();
1878
1879 /* Align __va_arg to a doubleword boundary if necessary. */
1880 arg = build3 (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg,
1881 NULL_TREE);
1882 align = type == NULL_TREE ? 0 : TYPE_ALIGN (type) / BITS_PER_WORD;
1883 if (align > 1)
1884 {
1885 t = build2 (PLUS_EXPR, TREE_TYPE (arg), arg, size_int (align - 1));
1886 arg_align = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
1887 build_int_cst (NULL_TREE, -align));
1888 gimplify_expr (&arg_align, pre_p, NULL, is_gimple_val, fb_rvalue);
1889 }
1890 else
1891 arg_align = arg;
1892
1893 /* Make sure the argument fits within the remainder of the saved
1894 register area, and branch to the stack logic if not. */
1895 u = fold_convert (TREE_TYPE (arg), arg_align);
1896 /* if (arg_align > 8 - wsize) goto lab_stack */
1897 t = fold_convert (TREE_TYPE (arg), size_int (8 - wsize));
1898 t = build2 (GT_EXPR, boolean_type_node, u, t);
1899 u = build1 (GOTO_EXPR, void_type_node, lab_stack);
1900 t = build3 (COND_EXPR, void_type_node, t, u, NULL_TREE);
1901 gimplify_and_add (t, pre_p);
1902
1903 /* Compute the argument address. */
1904 reg = build3 (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg,
1905 NULL_TREE);
1906 t = build2 (MULT_EXPR, TREE_TYPE (reg), arg_align,
1907 size_int (UNITS_PER_WORD));
1908 t = build2 (PLUS_EXPR, TREE_TYPE (reg), reg, t);
1909
1910 t = build2 (MODIFY_EXPR, void_type_node, addr, t);
1911 gimplify_and_add (t, pre_p);
1912
1913 /* Increment __va_arg. */
1914 t = build2 (PLUS_EXPR, TREE_TYPE (arg), arg_align, size_int (wsize));
1915 t = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg, t);
1916 gimplify_and_add (t, pre_p);
1917
1918 t = build1 (GOTO_EXPR, void_type_node, lab_done);
1919 gimplify_and_add (t, pre_p);
1920
1921 t = build1 (LABEL_EXPR, void_type_node, lab_stack);
1922 append_to_statement_list (t, pre_p);
1923 }
1924
1925 {
1926 tree stk;
1927 tree u;
1928
1929 stk = build3 (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk,
1930 NULL_TREE);
1931
1932 /* Align __va_stk to the type boundary if necessary. */
1933 align = type == NULL_TREE ? 0 : TYPE_ALIGN (type) / BITS_PER_UNIT;
1934 if (align > UNITS_PER_WORD)
1935 {
1936 t = build2 (PLUS_EXPR, TREE_TYPE (stk), stk, size_int (align - 1));
1937 t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
1938 build_int_cst (NULL_TREE, -align));
1939 gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
1940 }
1941 else
1942 t = stk;
1943
1944 /* Compute the argument address. */
1945 u = build2 (MODIFY_EXPR, void_type_node, addr, t);
1946 gimplify_and_add (u, pre_p);
1947
1948 /* Increment __va_stk. */
1949 t = build2 (PLUS_EXPR, TREE_TYPE (t), t, size_int (wsize * UNITS_PER_WORD));
1950 t = build2 (MODIFY_EXPR, TREE_TYPE (stk), stk, t);
1951 gimplify_and_add (t, pre_p);
1952 }
1953
1954 if (lab_done)
1955 {
1956 t = build1 (LABEL_EXPR, void_type_node, lab_done);
1957 append_to_statement_list (t, pre_p);
1958 }
1959
1960 addr = fold_convert (ptrtype, addr);
1961 return build_va_arg_indirect_ref (addr);
1962 }
1963
1964 /* If cmpsi has not been generated, emit code to do the test. Return the
1965 expression describing the test of operator OP. */
1966
1967 rtx
emit_test(enum rtx_code op,enum machine_mode mode)1968 emit_test (enum rtx_code op, enum machine_mode mode)
1969 {
1970 if (m88k_compare_reg == NULL_RTX)
1971 emit_insn (gen_test (m88k_compare_op0, m88k_compare_op1));
1972 return (gen_rtx_fmt_ee (op, mode, m88k_compare_reg, const0_rtx));
1973 }
1974
1975 /* Determine how to best perform cmpsi/bxx, where cmpsi has a constant
1976 operand. All tests with zero (albeit swapped) and all equality tests
1977 with a constant are done with bcnd. The remaining cases are swapped
1978 as needed. */
1979
1980 void
emit_bcnd(enum rtx_code op,rtx label)1981 emit_bcnd (enum rtx_code op, rtx label)
1982 {
1983 if (m88k_compare_op1 == const0_rtx)
1984 emit_jump_insn (gen_bcnd
1985 (gen_rtx_fmt_ee (op, VOIDmode, m88k_compare_op0, const0_rtx),
1986 label));
1987 else if (m88k_compare_op0 == const0_rtx)
1988 emit_jump_insn (gen_bcnd
1989 (gen_rtx_fmt_ee (swap_condition (op),
1990 VOIDmode, m88k_compare_op1, const0_rtx),
1991 label));
1992 else if (op != EQ && op != NE)
1993 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
1994 else
1995 {
1996 rtx zero = gen_reg_rtx (SImode);
1997 rtx reg, constant;
1998 int value;
1999
2000 if (GET_CODE (m88k_compare_op1) == CONST_INT)
2001 {
2002 reg = force_reg (SImode, m88k_compare_op0);
2003 constant = m88k_compare_op1;
2004 }
2005 else
2006 {
2007 reg = force_reg (SImode, m88k_compare_op1);
2008 constant = m88k_compare_op0;
2009 }
2010 value = INTVAL (constant);
2011
2012 /* Perform an arithmetic computation to make the compared-to value
2013 zero, but avoid loosing if the bcnd is later changed into sxx. */
2014 if (SMALL_INTVAL (value))
2015 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2016 else
2017 {
2018 if (SMALL_INTVAL (-value))
2019 emit_insn (gen_addsi3 (zero, reg,
2020 GEN_INT (-value)));
2021 else
2022 emit_insn (gen_xorsi3 (zero, reg, constant));
2023
2024 emit_jump_insn (gen_bcnd (gen_rtx_fmt_ee (op, VOIDmode,
2025 zero, const0_rtx),
2026 label));
2027 }
2028 }
2029 }
2030
2031 /* Print an operand. Recognize special options, documented below. */
2032
2033 void
print_operand(FILE * file,rtx x,int code)2034 print_operand (FILE *file, rtx x, int code)
2035 {
2036 enum rtx_code xc = (x ? GET_CODE (x) : UNKNOWN);
2037 int value = (xc == CONST_INT ? INTVAL (x) : 0);
2038 static int sequencep;
2039 static int reversep;
2040
2041 if (sequencep)
2042 {
2043 if (code < 'B' || code > 'E')
2044 output_operand_lossage ("%%R not followed by %%B/C/D/E");
2045 if (reversep)
2046 xc = reverse_condition (xc);
2047 sequencep = 0;
2048 }
2049
2050 switch (code)
2051 {
2052 case '#': /* register prefix character (may be empty) */
2053 fputs (m88k_register_prefix, file);
2054 return;
2055
2056 case 'V': /* Output a serializing instruction as needed if the operand
2057 (assumed to be a MEM) is a volatile load. */
2058 case 'v': /* ditto for a volatile store. */
2059 if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE)
2060 {
2061 /* The m88110 implements two FIFO queues, one for loads and
2062 one for stores. These queues mean that loads complete in
2063 their issue order as do stores. An interaction between the
2064 history buffer and the store reservation station ensures
2065 that a store will not bypass load. Finally, a load will not
2066 bypass store, but only when they reference the same address.
2067
2068 To avoid this reordering (a load bypassing a store) for
2069 volatile references, a serializing instruction is output.
2070 We choose the fldcr instruction as it does not serialize on
2071 the m88100 so that -m88000 code will not be degraded.
2072
2073 The mechanism below is completed by having CC_STATUS_INIT set
2074 the code to the unknown value. */
2075
2076 /*
2077 hassey 6/30/93
2078 A problem with 88110 4.1 & 4.2 makes the use of fldcr for
2079 this purpose undesirable. Instead we will use tb1, this will
2080 cause serialization on the 88100 but such is life.
2081 */
2082
2083 static rtx last_addr = NULL_RTX;
2084 if (code == 'V' /* Only need to serialize before a load. */
2085 && m88k_volatile_code != 'V' /* Loads complete in FIFO order. */
2086 && !(m88k_volatile_code == 'v'
2087 && GET_CODE (XEXP (x, 0)) == LO_SUM
2088 && rtx_equal_p (XEXP (XEXP (x, 0), 1), last_addr)))
2089 asm_fprintf (file,
2090 #if 0
2091 "fldcr\t %R%s,%Rfcr63\n\t",
2092 #else /* 0 */
2093 "tb1\t 1,%R%s,0xff\n\t",
2094 #endif /* 0 */
2095 reg_names[0]);
2096 m88k_volatile_code = code;
2097 last_addr = (GET_CODE (XEXP (x, 0)) == LO_SUM
2098 ? XEXP (XEXP (x, 0), 1) : 0);
2099 }
2100 return;
2101
2102 case 'X': /* print the upper 16 bits... */
2103 value >>= 16;
2104 case 'x': /* print the lower 16 bits of the integer constant in hex */
2105 if (xc != CONST_INT)
2106 output_operand_lossage ("invalid %%x/X value");
2107 fprintf (file, "0x%x", value & 0xffff); return;
2108
2109 case 'H': /* print the low 16 bits of the negated integer constant */
2110 if (xc != CONST_INT)
2111 output_operand_lossage ("invalid %%H value");
2112 value = -value;
2113 case 'h': /* print the register or low 16 bits of the integer constant */
2114 if (xc == REG)
2115 goto reg;
2116 if (xc != CONST_INT)
2117 output_operand_lossage ("invalid %%h value");
2118 fprintf (file, "%d", value & 0xffff);
2119 return;
2120
2121 case 'Q': /* print the low 8 bits of the negated integer constant */
2122 if (xc != CONST_INT)
2123 output_operand_lossage ("invalid %%Q value");
2124 value = -value;
2125 case 'q': /* print the register or low 8 bits of the integer constant */
2126 if (xc == REG)
2127 goto reg;
2128 if (xc != CONST_INT)
2129 output_operand_lossage ("invalid %%q value");
2130 fprintf (file, "%d", value & 0xff);
2131 return;
2132
2133 case 'p': /* print the logarithm of the integer constant */
2134 if (xc != CONST_INT
2135 || (value = exact_log2 (value)) < 0)
2136 output_operand_lossage ("invalid %%p value");
2137 fprintf (file, "%d", value);
2138 return;
2139
2140 case 'S': /* complement the value and then... */
2141 value = ~value;
2142 case 's': /* print the width and offset values forming the integer
2143 constant with a SET instruction. See integer_ok_for_set. */
2144 {
2145 unsigned mask, uval = value;
2146 int top, bottom;
2147
2148 if (xc != CONST_INT)
2149 output_operand_lossage ("invalid %%s/S value");
2150 /* All the "one" bits must be contiguous. If so, MASK will be
2151 a power of two or zero. */
2152 mask = (uval | (uval - 1)) + 1;
2153 if (!(uval && POWER_OF_2_or_0 (mask)))
2154 output_operand_lossage ("invalid %%s/S value");
2155 top = mask ? exact_log2 (mask) : 32;
2156 bottom = exact_log2 (uval & ~(uval - 1));
2157 fprintf (file,"%d<%d>", top - bottom, bottom);
2158 return;
2159 }
2160
2161 case 'P': /* print nothing if pc_rtx; output label_ref */
2162 if (xc == LABEL_REF)
2163 output_addr_const (file, x);
2164 else if (xc != PC)
2165 output_operand_lossage ("invalid %%P operand");
2166 return;
2167
2168 case 'L': /* print 0 or 1 if operand is label_ref and then... */
2169 fputc (xc == LABEL_REF ? '1' : '0', file);
2170 case '.': /* print .n if delay slot is used */
2171 fputs ((final_sequence
2172 && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
2173 ? ".n\t" : "\t", file);
2174 return;
2175
2176 case '!': /* Reverse the following condition. */
2177 sequencep++;
2178 reversep = 1;
2179 return;
2180 case 'R': /* reverse the condition of the next print_operand
2181 if operand is a label_ref. */
2182 sequencep++;
2183 reversep = (xc == LABEL_REF);
2184 return;
2185
2186 case 'B': /* bcnd branch values */
2187 if (0) /* SVR4 */
2188 fputs (m88k_register_prefix, file);
2189 switch (xc)
2190 {
2191 case EQ: fputs ("eq0", file); return;
2192 case NE: fputs ("ne0", file); return;
2193 case GT: fputs ("gt0", file); return;
2194 case LE: fputs ("le0", file); return;
2195 case LT: fputs ("lt0", file); return;
2196 case GE: fputs ("ge0", file); return;
2197 default: output_operand_lossage ("invalid %%B value");
2198 }
2199
2200 case 'C': /* bb0/bb1 branch values for comparisons */
2201 if (0) /* SVR4 */
2202 fputs (m88k_register_prefix, file);
2203 switch (xc)
2204 {
2205 case EQ: fputs ("eq", file); return;
2206 case NE: fputs ("ne", file); return;
2207 case GT: fputs ("gt", file); return;
2208 case LE: fputs ("le", file); return;
2209 case LT: fputs ("lt", file); return;
2210 case GE: fputs ("ge", file); return;
2211 case GTU: fputs ("hi", file); return;
2212 case LEU: fputs ("ls", file); return;
2213 case LTU: fputs ("lo", file); return;
2214 case GEU: fputs ("hs", file); return;
2215 default: output_operand_lossage ("invalid %%C value");
2216 }
2217
2218 case 'D': /* bcnd branch values for float comparisons */
2219 switch (xc)
2220 {
2221 case EQ: fputs ("0xa", file); return;
2222 case NE: fputs ("0x5", file); return;
2223 case GT:
2224 if (0) /* SVR4 */
2225 fputs (m88k_register_prefix, file);
2226 fputs ("gt0", file);
2227 return;
2228 case LE:
2229 if (0) /* SVR4 */
2230 fputs (m88k_register_prefix, file);
2231 fputs ("le0", file);
2232 return;
2233 case LT: fputs ("0x4", file); return;
2234 case GE: fputs ("0xb", file); return;
2235 default: output_operand_lossage ("invalid %%D value");
2236 }
2237
2238 case 'E': /* bcnd branch values for special integers */
2239 switch (xc)
2240 {
2241 case EQ: fputs ("0x8", file); return;
2242 case NE: fputs ("0x7", file); return;
2243 default: output_operand_lossage ("invalid %%E value");
2244 }
2245
2246 case 'd': /* second register of a two register pair */
2247 if (xc != REG)
2248 output_operand_lossage ("`%%d' operand isn't a register");
2249 asm_fprintf (file, "%R%s", reg_names[REGNO (x) + 1]);
2250 return;
2251
2252 case 'r': /* an immediate 0 should be represented as `r0' */
2253 if (x == const0_rtx)
2254 {
2255 asm_fprintf (file, "%R%s", reg_names[0]);
2256 return;
2257 }
2258 else if (xc != REG)
2259 output_operand_lossage ("invalid %%r value");
2260 case 0:
2261 name:
2262 if (xc == REG)
2263 {
2264 reg:
2265 if (REGNO (x) == ARG_POINTER_REGNUM)
2266 output_operand_lossage ("operand is r0");
2267 else
2268 asm_fprintf (file, "%R%s", reg_names[REGNO (x)]);
2269 }
2270 else if (xc == PLUS)
2271 output_address (x);
2272 else if (xc == MEM)
2273 output_address (XEXP (x, 0));
2274 else if (flag_pic && xc == UNSPEC)
2275 {
2276 output_addr_const (file, XVECEXP (x, 0, 0));
2277 fputs ("#got_rel", file);
2278 }
2279 else if (xc == CONST_DOUBLE)
2280 output_operand_lossage ("operand is const_double");
2281 else
2282 output_addr_const (file, x);
2283 return;
2284
2285 case 'g': /* append #got_rel as needed */
2286 if (flag_pic && (xc == SYMBOL_REF || xc == LABEL_REF))
2287 {
2288 output_addr_const (file, x);
2289 fputs ("#got_rel", file);
2290 return;
2291 }
2292 goto name;
2293
2294 case 'a': /* (standard), assume operand is an address */
2295 case 'c': /* (standard), assume operand is an immediate value */
2296 case 'l': /* (standard), assume operand is a label_ref */
2297 case 'n': /* (standard), like %c, except negate first */
2298 default:
2299 output_operand_lossage ("invalid code");
2300 }
2301 }
2302
2303 void
print_operand_address(FILE * file,rtx addr)2304 print_operand_address (FILE *file, rtx addr)
2305 {
2306 rtx reg0, reg1;
2307
2308 switch (GET_CODE (addr))
2309 {
2310 case REG:
2311 gcc_assert (REGNO (addr) != ARG_POINTER_REGNUM);
2312 asm_fprintf (file, "%R%s,%R%s", reg_names[0], reg_names [REGNO (addr)]);
2313 break;
2314
2315 case LO_SUM:
2316 asm_fprintf (file, "%R%s,%Rlo16(",
2317 reg_names[REGNO (XEXP (addr, 0))]);
2318 output_addr_const (file, XEXP (addr, 1));
2319 fputc (')', file);
2320 break;
2321
2322 case PLUS:
2323 reg0 = XEXP (addr, 0);
2324 reg1 = XEXP (addr, 1);
2325 if (GET_CODE (reg0) == MULT || GET_CODE (reg0) == CONST_INT)
2326 {
2327 rtx tmp = reg0;
2328 reg0 = reg1;
2329 reg1 = tmp;
2330 }
2331
2332 gcc_assert ((!REG_P (reg0) || REGNO (reg0) != ARG_POINTER_REGNUM)
2333 && (!REG_P (reg1) || REGNO (reg1) != ARG_POINTER_REGNUM));
2334
2335 if (REG_P (reg0))
2336 {
2337 if (REG_P (reg1))
2338 asm_fprintf (file, "%R%s,%R%s",
2339 reg_names [REGNO (reg0)], reg_names [REGNO (reg1)]);
2340
2341 else if (GET_CODE (reg1) == CONST_INT)
2342 asm_fprintf (file, "%R%s,%d",
2343 reg_names [REGNO (reg0)], INTVAL (reg1));
2344
2345 else if (GET_CODE (reg1) == MULT)
2346 {
2347 rtx mreg = XEXP (reg1, 0);
2348 gcc_assert (REGNO (mreg) != ARG_POINTER_REGNUM);
2349
2350 asm_fprintf (file, "%R%s[%R%s]", reg_names[REGNO (reg0)],
2351 reg_names[REGNO (mreg)]);
2352 }
2353
2354 else if (GET_CODE (reg1) == ZERO_EXTRACT)
2355 {
2356 asm_fprintf (file, "%R%s,%Rlo16(",
2357 reg_names[REGNO (reg0)]);
2358 output_addr_const (file, XEXP (reg1, 0));
2359 fputc (')', file);
2360 }
2361
2362 else if (flag_pic)
2363 {
2364 asm_fprintf (file, "%R%s,", reg_names[REGNO (reg0)]);
2365 output_addr_const (file, reg1);
2366 fputs ("#got_rel", file);
2367 }
2368 else
2369 gcc_unreachable ();
2370 }
2371
2372 else
2373 gcc_unreachable ();
2374 break;
2375
2376 case MULT:
2377 gcc_assert (REGNO (XEXP (addr, 0)) != ARG_POINTER_REGNUM);
2378 asm_fprintf (file, "%R%s[%R%s]",
2379 reg_names[0], reg_names[REGNO (XEXP (addr, 0))]);
2380 break;
2381
2382 case CONST_INT:
2383 asm_fprintf (file, "%R%s,%d", reg_names[0], INTVAL (addr));
2384 break;
2385
2386 default:
2387 asm_fprintf (file, "%R%s,", reg_names[0]);
2388 output_addr_const (file, addr);
2389 }
2390 }
2391
2392 /* Return true if X is an address which needs a temporary register when
2393 reloaded while generating PIC code. */
2394
2395 bool
pic_address_needs_scratch(rtx x)2396 pic_address_needs_scratch (rtx x)
2397 {
2398 /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */
2399 if (GET_CODE (x) == CONST)
2400 {
2401 x = XEXP (x, 0);
2402 if (GET_CODE (x) == PLUS)
2403 {
2404 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
2405 && GET_CODE (XEXP (x, 1)) == CONST_INT
2406 && ! ADD_INT (XEXP (x, 1)))
2407 return true;
2408 }
2409 }
2410
2411 return false;
2412 }
2413
2414 /* Adjust the cost of INSN based on the relationship between INSN that
2415 is dependent on DEP_INSN through the dependence LINK. The default
2416 is to make no adjustment to COST.
2417
2418 On the m88k, ignore the cost of anti- and output-dependencies. On
2419 the m88100, a store can issue two cycles before the value (not the
2420 address) has finished computing. */
2421
2422 static int
m88k_adjust_cost(rtx insn,rtx link,rtx dep,int cost)2423 m88k_adjust_cost (rtx insn, rtx link, rtx dep, int cost)
2424 {
2425 if (REG_NOTE_KIND (link) != REG_DEP_TRUE)
2426 return 0; /* Anti or output dependence. */
2427
2428 if (TARGET_88110
2429 && recog_memoized (insn) >= 0
2430 && get_attr_type (insn) == TYPE_STORE
2431 && SET_SRC (PATTERN (insn)) == SET_DEST (PATTERN (dep)))
2432 return cost - 4; /* 88110 store reservation station. */
2433
2434 return cost;
2435 }
2436
2437 /* Return cost of address expression X.
2438 Expect that X is properly formed address reference. */
2439
2440 static int
m88k_address_cost(rtx x)2441 m88k_address_cost (rtx x)
2442 {
2443 /* REG+REG is made slightly more expensive because it might keep
2444 a register live for longer than we might like. */
2445 switch (GET_CODE (x))
2446 {
2447 case REG:
2448 case LO_SUM:
2449 case MULT:
2450 return 1;
2451 case HIGH:
2452 return 2;
2453 case PLUS:
2454 return (REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1))) ? 2 : 1;
2455 default:
2456 return 4;
2457 }
2458 }
2459
2460 /* Compute the cost of computing a constant rtl expression x
2461 whose rtx-code is code. */
2462 static bool
m88k_rtx_costs(rtx x,int code,int outer_code,int * total)2463 m88k_rtx_costs (rtx x, int code, int outer_code, int *total)
2464 {
2465 switch (code)
2466 {
2467 case CONST_INT:
2468 /* We assume that any 16 bit integer can easily be recreated, so we
2469 indicate 0 cost, in an attempt to get GCC not to optimize things
2470 like comparison against a constant. */
2471 if (SMALL_INT (x))
2472 *total = 0;
2473 else if (SMALL_INTVAL (- INTVAL (x)))
2474 *total = 2;
2475 else if (classify_integer (SImode, INTVAL (x)) != m88k_oru_or)
2476 *total = 4;
2477 *total = 7;
2478 return true;
2479
2480 case HIGH:
2481 *total = 2;
2482 return true;
2483
2484 case CONST:
2485 case LABEL_REF:
2486 case SYMBOL_REF:
2487 if (flag_pic)
2488 *total = (flag_pic == 2) ? 11 : 8;
2489 else
2490 *total = 5;
2491 return true;
2492
2493 /* The cost of CONST_DOUBLE is zero (if it can be placed in an insn,
2494 it is as good as a register; since it can't be placed in any insn,
2495 it won't do anything in cse, but it will cause expand_binop to
2496 pass the constant to the define_expands). */
2497 case CONST_DOUBLE:
2498 *total = 0;
2499 return true;
2500
2501 case MEM:
2502 *total = COSTS_N_INSNS (2);
2503 return true;
2504
2505 case MULT:
2506 *total = COSTS_N_INSNS (3);
2507 return true;
2508
2509 case DIV:
2510 case UDIV:
2511 case MOD:
2512 case UMOD:
2513 *total = COSTS_N_INSNS (38);
2514 return true;
2515
2516 default:
2517 return false;
2518 }
2519 }
2520
2521 static bool
m88k_handle_option(size_t code,const char * arg,int value)2522 m88k_handle_option (size_t code, const char *arg, int value)
2523 {
2524 switch (code)
2525 {
2526 case OPT_m88000:
2527 /* make the cpu type nonzero; will be reset in m88k_override_options() */
2528 target_flags |= MASK_88100 | MASK_88110;
2529 return true;
2530
2531 case OPT_m88100:
2532 target_flags &= ~MASK_88110;
2533 target_flags |= MASK_88100;
2534 return true;
2535
2536 case OPT_m88110:
2537 target_flags &= ~MASK_88100;
2538 target_flags |= MASK_88110;
2539 return true;
2540
2541 default:
2542 return true;
2543 }
2544 }
2545
2546 void
m88k_override_options(void)2547 m88k_override_options (void)
2548 {
2549 if (!TARGET_88100 && !TARGET_88110)
2550 target_flags |= CPU_DEFAULT;
2551
2552 if (TARGET_88100 && TARGET_88110)
2553 target_flags &= ~(MASK_88100 | MASK_88110);
2554
2555 if (TARGET_88110)
2556 {
2557 target_flags |= MASK_USE_DIV;
2558 target_flags &= ~MASK_CHECK_ZERO_DIV;
2559 }
2560
2561 m88k_cpu = (TARGET_88110 ? PROCESSOR_M88100
2562 : (TARGET_88100 ? PROCESSOR_M88100 : PROCESSOR_M88000));
2563
2564 if (TARGET_TRAP_LARGE_SHIFT && TARGET_HANDLE_LARGE_SHIFT)
2565 error ("-mtrap-large-shift and -mhandle-large-shift are incompatible");
2566
2567 if (TARGET_OMIT_LEAF_FRAME_POINTER) /* keep nonleaf frame pointers */
2568 flag_omit_frame_pointer = 1;
2569
2570 /* On the m88100, it is desirable to align functions to a cache line.
2571 The m88110 cache is small, so align to an 8 byte boundary. */
2572 if (align_functions == 0)
2573 align_functions = TARGET_88100 ? 16 : 8;
2574
2575 #if 1 /* XXX breaks -freorder-blocks and even without it, tree-cfg.c */
2576 flag_delayed_branch = 0;
2577 #endif
2578
2579 /* XXX -freorder-blocks (enabled at -O2) does not work with -fdelayed-branch
2580 yet. */
2581 if (flag_delayed_branch)
2582 {
2583 flag_reorder_blocks = flag_reorder_blocks_and_partition = 0;
2584 }
2585 }
2586