1 /* Subroutines for insn-output.c for Motorola 88000.
2 Copyright (C) 1988, 1989, 1990, 1991 Free Software Foundation, Inc.
3 Contributed by Michael Tiemann (tiemann@mcc.com)
4 Enhanced by Michael Meissner (meissner@osf.org)
5 Currently supported by Tom Wood (wood@dg-rtp.dg.com)
7 This file is part of GNU CC.
9 GNU CC 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)
14 GNU CC 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.
19 You should have received a copy of the GNU General Public License
20 along with GNU CC; see the file COPYING. If not, write to
21 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
25 #include <sys/types.h>
32 #include "hard-reg-set.h"
34 #include "insn-config.h"
35 #include "conditions.h"
36 #include "insn-flags.h"
38 #include "insn-attr.h"
44 extern char *version_string;
45 extern time_t time ();
46 extern char *ctime ();
47 extern int flag_traditional;
48 extern FILE *asm_out_file;
50 static char out_sccs_id[] = "@(#)m88k.c 2.2.13.5 10/19/92 15:27:15";
51 static char tm_sccs_id [] = TM_SCCS_ID;
53 char *m88k_pound_sign = ""; /* Either # for SVR4 or empty for SVR3 */
54 char *m88k_short_data;
56 char m88k_volatile_code;
58 int m88k_gp_threshold;
59 int m88k_prologue_done = 0; /* Ln directives can now be emitted */
60 int m88k_function_number = 0; /* Counter unique to each function */
61 int m88k_fp_offset = 0; /* offset of frame pointer if used */
62 int m88k_stack_size = 0; /* size of allocated stack (including frame) */
64 int m88k_version_0300; /* Version is at least 03.00 */
66 rtx m88k_compare_reg; /* cmp output pseudo register */
67 rtx m88k_compare_op0; /* cmpsi operand 0 */
68 rtx m88k_compare_op1; /* cmpsi operand 1 */
70 enum attr_cpu m88k_cpu; /* target cpu */
72 /* Determine what instructions are needed to manufacture the integer VALUE
76 classify_integer (mode, value)
77 enum machine_mode mode;
84 else if (SMALL_INTVAL (value))
86 else if (SMALL_INTVAL (-value))
88 else if (mode == HImode)
90 else if (mode == QImode)
92 else if ((value & 0xffff) == 0)
94 else if (integer_ok_for_set (value))
100 /* Return the bit number in a compare word corresponding to CONDITION. */
103 condition_value (condition)
106 switch (GET_CODE (condition))
123 integer_ok_for_set (value)
124 register unsigned value;
126 /* All the "one" bits must be contiguous. If so, MASK + 1 will be
127 a power of two or zero. */
128 register unsigned mask = (value | (value - 1));
129 return (value && POWER_OF_2_or_0 (mask + 1));
133 output_load_const_int (mode, operands)
134 enum machine_mode mode;
137 static char *patterns[] =
145 "or.u %0,%#r0,%X1\n\tor %0,%0,%x1",
148 if (! REG_P (operands[0])
149 || GET_CODE (operands[1]) != CONST_INT)
151 return patterns[classify_integer (mode, INTVAL (operands[1]))];
154 /* These next two routines assume that floating point numbers are represented
155 in a manner which is consistent between host and target machines. */
158 output_load_const_float (operands)
161 /* These can return 0 under some circumstances when cross-compiling. */
162 operands[0] = operand_subword (operands[0], 0, 0, SFmode);
163 operands[1] = operand_subword (operands[1], 0, 0, SFmode);
165 return output_load_const_int (SImode, operands);
169 output_load_const_double (operands)
174 /* These can return zero on some cross-compilers, but there's nothing
175 we can do about it. */
176 latehalf[0] = operand_subword (operands[0], 1, 0, DFmode);
177 latehalf[1] = operand_subword (operands[1], 1, 0, DFmode);
179 operands[0] = operand_subword (operands[0], 0, 0, DFmode);
180 operands[1] = operand_subword (operands[1], 0, 0, DFmode);
182 output_asm_insn (output_load_const_int (SImode, operands), operands);
184 operands[0] = latehalf[0];
185 operands[1] = latehalf[1];
187 return output_load_const_int (SImode, operands);
191 output_load_const_dimode (operands)
196 latehalf[0] = operand_subword (operands[0], 1, 0, DImode);
197 latehalf[1] = operand_subword (operands[1], 1, 0, DImode);
199 operands[0] = operand_subword (operands[0], 0, 0, DImode);
200 operands[1] = operand_subword (operands[1], 0, 0, DImode);
202 output_asm_insn (output_load_const_int (SImode, operands), operands);
204 operands[0] = latehalf[0];
205 operands[1] = latehalf[1];
207 return output_load_const_int (SImode, operands);
210 /* Emit insns to move operands[1] into operands[0].
212 Return 1 if we have written out everything that needs to be done to
213 do the move. Otherwise, return 0 and the caller will emit the move
216 SCRATCH if non zero can be used as a scratch register for the move
217 operation. It is provided by a SECONDARY_RELOAD_* macro if needed. */
220 emit_move_sequence (operands, mode, scratch)
222 enum machine_mode mode;
225 register rtx operand0 = operands[0];
226 register rtx operand1 = operands[1];
228 /* Handle most common case first: storing into a register. */
229 if (register_operand (operand0, mode))
231 if (register_operand (operand1, mode)
232 || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
233 || GET_CODE (operand1) == HIGH
234 /* Only `general_operands' can come here, so MEM is ok. */
235 || GET_CODE (operand1) == MEM)
237 /* Run this case quickly. */
238 emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
242 else if (GET_CODE (operand0) == MEM)
244 if (register_operand (operand1, mode)
245 || (operand1 == const0_rtx && GET_MODE_SIZE (mode) <= UNITS_PER_WORD))
247 /* Run this case quickly. */
248 emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
251 if (! reload_in_progress && ! reload_completed)
253 operands[0] = validize_mem (operand0);
254 operands[1] = operand1 = force_reg (mode, operand1);
258 /* Simplify the source if we need to. */
259 if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
261 if (GET_CODE (operand1) != CONST_INT
262 && GET_CODE (operand1) != CONST_DOUBLE)
264 rtx temp = ((reload_in_progress || reload_completed)
266 operands[1] = legitimize_address (flag_pic
267 && symbolic_address_p (operand1),
268 operand1, temp, scratch);
270 operands[1] = gen_rtx (SUBREG, mode, operands[1], 0);
274 /* Now have insn-emit do whatever it normally does. */
278 /* Return a legitimate reference for ORIG (either an address or a MEM)
279 using the register REG. If PIC and the address is already
280 position-independent, use ORIG. Newly generated position-independent
281 addresses go into a reg. This is REG if non zero, otherwise we
282 allocate register(s) as necessary. If this is called during reload,
283 and we need a second temp register, then we use SCRATCH, which is
284 provided via the SECONDARY_INPUT_RELOAD_CLASS mechanism. */
287 legitimize_address (pic, orig, reg, scratch)
293 rtx addr = (GET_CODE (orig) == MEM ? XEXP (orig, 0) : orig);
299 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
303 if (reload_in_progress || reload_completed)
306 reg = gen_reg_rtx (Pmode);
311 /* If not during reload, allocate another temp reg here for
312 loading in the address, so that these instructions can be
313 optimized properly. */
314 temp = ((reload_in_progress || reload_completed)
315 ? reg : gen_reg_rtx (Pmode));
317 emit_insn (gen_rtx (SET, VOIDmode,
318 temp, gen_rtx (HIGH, SImode, addr)));
319 emit_insn (gen_rtx (SET, VOIDmode,
320 temp, gen_rtx (LO_SUM, SImode, temp, addr)));
323 new = gen_rtx (MEM, Pmode,
324 gen_rtx (PLUS, SImode,
325 pic_offset_table_rtx, addr));
326 current_function_uses_pic_offset_table = 1;
327 RTX_UNCHANGING_P (new) = 1;
328 insn = emit_move_insn (reg, new);
329 /* Put a REG_EQUAL note on this insn, so that it can be optimized
331 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, orig,
335 else if (GET_CODE (addr) == CONST)
339 if (GET_CODE (XEXP (addr, 0)) == PLUS
340 && XEXP (XEXP (addr, 0), 0) == pic_offset_table_rtx)
345 if (reload_in_progress || reload_completed)
348 reg = gen_reg_rtx (Pmode);
351 if (GET_CODE (XEXP (addr, 0)) != PLUS) abort ();
353 base = legitimize_address (1, XEXP (XEXP (addr, 0), 0), reg, 0);
354 addr = legitimize_address (1, XEXP (XEXP (addr, 0), 1),
355 base == reg ? 0 : reg, 0);
357 if (GET_CODE (addr) == CONST_INT)
359 if (SMALL_INT (addr))
360 return plus_constant_for_output (base, INTVAL (addr));
361 else if (! reload_in_progress && ! reload_completed)
362 addr = force_reg (Pmode, addr);
363 /* We can't create any new registers during reload, so use the
364 SCRATCH reg provided by the reload_insi pattern. */
367 emit_move_insn (scratch, addr);
371 /* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS
372 macro needs to be adjusted so that a scratch reg is provided
376 new = gen_rtx (PLUS, SImode, base, addr);
377 /* Should we set special REG_NOTEs here? */
380 else if (! SHORT_ADDRESS_P (addr, temp))
384 if (reload_in_progress || reload_completed)
387 reg = gen_reg_rtx (Pmode);
390 emit_insn (gen_rtx (SET, VOIDmode,
391 reg, gen_rtx (HIGH, SImode, addr)));
392 new = gen_rtx (LO_SUM, SImode, reg, addr);
396 && GET_CODE (orig) == MEM)
398 new = gen_rtx (MEM, GET_MODE (orig), new);
399 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (orig);
400 MEM_VOLATILE_P (new) = MEM_VOLATILE_P (orig);
401 MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (orig);
406 /* Support functions for code to emit a block move. There are four methods
407 used to perform the block move:
409 + call the looping library function, e.g. __movstrSI64n8
410 + call a non-looping library function, e.g. __movstrHI15x11
411 + produce an inline sequence of ld/st instructions
413 The parameters below describe the library functions produced by
416 #define MOVSTR_LOOP 64 /* __movstrSI64n68 .. __movstrSI64n8 */
417 #define MOVSTR_QI 16 /* __movstrQI16x16 .. __movstrQI16x2 */
418 #define MOVSTR_HI 48 /* __movstrHI48x48 .. __movstrHI48x4 */
419 #define MOVSTR_SI 96 /* __movstrSI96x96 .. __movstrSI96x8 */
420 #define MOVSTR_DI 96 /* __movstrDI96x96 .. __movstrDI96x16 */
421 #define MOVSTR_ODD_HI 16 /* __movstrHI15x15 .. __movstrHI15x5 */
422 #define MOVSTR_ODD_SI 48 /* __movstrSI47x47 .. __movstrSI47x11,
423 __movstrSI46x46 .. __movstrSI46x10,
424 __movstrSI45x45 .. __movstrSI45x9 */
425 #define MOVSTR_ODD_DI 48 /* __movstrDI47x47 .. __movstrDI47x23,
426 __movstrDI46x46 .. __movstrDI46x22,
427 __movstrDI45x45 .. __movstrDI45x21,
428 __movstrDI44x44 .. __movstrDI44x20,
429 __movstrDI43x43 .. __movstrDI43x19,
430 __movstrDI42x42 .. __movstrDI42x18,
431 __movstrDI41x41 .. __movstrDI41x17 */
433 /* Limits for using the non-looping movstr functions. For the m88100
434 processor, we assume the source and destination are word aligned.
435 The QImode and HImode limits are the break even points where memcpy
436 does just as well and beyond which memcpy does better. For the
437 m88110, we tend to assume double word alignment, but also analyze
438 the word aligned cases. The analysis is complicated because memcpy
439 may use the cache control instructions for better performance. */
441 #define MOVSTR_QI_LIMIT_88100 13
442 #define MOVSTR_HI_LIMIT_88100 38
443 #define MOVSTR_SI_LIMIT_88100 MOVSTR_SI
444 #define MOVSTR_DI_LIMIT_88100 MOVSTR_SI
446 #define MOVSTR_QI_LIMIT_88000 16
447 #define MOVSTR_HI_LIMIT_88000 38
448 #define MOVSTR_SI_LIMIT_88000 72
449 #define MOVSTR_DI_LIMIT_88000 72
451 #define MOVSTR_QI_LIMIT_88110 16
452 #define MOVSTR_HI_LIMIT_88110 38
453 #define MOVSTR_SI_LIMIT_88110 72
454 #define MOVSTR_DI_LIMIT_88110 72
456 static enum machine_mode mode_from_align[] =
457 {VOIDmode, QImode, HImode, VOIDmode, SImode,
458 VOIDmode, VOIDmode, VOIDmode, DImode};
459 static int max_from_align[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI,
461 static int all_from_align[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0, MOVSTR_ODD_SI,
462 0, 0, 0, MOVSTR_ODD_DI};
464 static int best_from_align[3][9] =
465 {0, MOVSTR_QI_LIMIT_88100, MOVSTR_HI_LIMIT_88100, 0, MOVSTR_SI_LIMIT_88100,
466 0, 0, 0, MOVSTR_DI_LIMIT_88100,
467 0, MOVSTR_QI_LIMIT_88110, MOVSTR_HI_LIMIT_88110, 0, MOVSTR_SI_LIMIT_88110,
468 0, 0, 0, MOVSTR_DI_LIMIT_88110,
469 0, MOVSTR_QI_LIMIT_88000, MOVSTR_HI_LIMIT_88000, 0, MOVSTR_SI_LIMIT_88000,
470 0, 0, 0, MOVSTR_DI_LIMIT_88000};
472 static void block_move_loop ();
473 static void block_move_no_loop ();
474 static void block_move_sequence ();
476 /* Emit code to perform a block move. Choose the best method.
478 OPERANDS[0] is the destination.
479 OPERANDS[1] is the source.
480 OPERANDS[2] is the size.
481 OPERANDS[3] is the alignment safe to use. */
484 expand_block_move (dest_mem, src_mem, operands)
489 int align = INTVAL (operands[3]);
490 int constp = (GET_CODE (operands[2]) == CONST_INT);
491 int bytes = (constp ? INTVAL (operands[2]) : 0);
492 int target = (int) m88k_cpu;
494 assert (CPU_M88100 == 0);
495 assert (CPU_M88110 == 1);
496 assert (CPU_M88000 == 2);
498 if (constp && bytes <= 0)
501 /* Determine machine mode to do move with. */
502 if (align > 4 && !TARGET_88110)
504 else if (align <= 0 || align == 3)
505 abort (); /* block move invalid alignment. */
507 if (constp && bytes <= 3 * align)
508 block_move_sequence (operands[0], dest_mem, operands[1], src_mem,
511 else if (constp && bytes <= best_from_align[target][align])
512 block_move_no_loop (operands[0], dest_mem, operands[1], src_mem,
515 else if (constp && align == 4 && TARGET_88100)
516 block_move_loop (operands[0], dest_mem, operands[1], src_mem,
521 #ifdef TARGET_MEM_FUNCTIONS
522 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"), 0,
526 operands[2], SImode);
528 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcopy"), 0,
532 operands[2], SImode);
537 /* Emit code to perform a block move by calling a looping movstr library
538 function. SIZE and ALIGN are known constants. DEST and SRC are
542 block_move_loop (dest, dest_mem, src, src_mem, size, align)
548 enum machine_mode mode;
557 /* Determine machine mode to do move with. */
561 /* Determine the structure of the loop. */
562 count = size / MOVSTR_LOOP;
563 units = (size - count * MOVSTR_LOOP) / align;
568 units += MOVSTR_LOOP / align;
573 block_move_no_loop (dest, dest_mem, src, src_mem, size, align);
577 remainder = size - count * MOVSTR_LOOP - units * align;
579 mode = mode_from_align[align];
580 sprintf (entry, "__movstr%s%dn%d",
581 GET_MODE_NAME (mode), MOVSTR_LOOP, units * align);
582 entry_name = get_identifier (entry);
584 offset_rtx = gen_rtx (CONST_INT, VOIDmode,
585 MOVSTR_LOOP + (1 - units) * align);
587 value_rtx = gen_rtx (MEM, mode,
588 gen_rtx (PLUS, Pmode,
589 gen_rtx (REG, Pmode, 3),
591 RTX_UNCHANGING_P (value_rtx) = RTX_UNCHANGING_P (src_mem);
592 MEM_VOLATILE_P (value_rtx) = MEM_VOLATILE_P (src_mem);
593 MEM_IN_STRUCT_P (value_rtx) = MEM_IN_STRUCT_P (src_mem);
595 emit_insn (gen_call_movstrsi_loop
596 (gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)),
597 dest, src, offset_rtx, value_rtx,
598 gen_rtx (REG, GET_MODE (value_rtx), ((units & 1) ? 4 : 5)),
599 gen_rtx (CONST_INT, VOIDmode, count)));
602 block_move_sequence (gen_rtx (REG, Pmode, 2), dest_mem,
603 gen_rtx (REG, Pmode, 3), src_mem,
604 remainder, align, MOVSTR_LOOP + align);
607 /* Emit code to perform a block move by calling a non-looping library
608 function. SIZE and ALIGN are known constants. DEST and SRC are
609 registers. OFFSET is the known starting point for the output pattern. */
612 block_move_no_loop (dest, dest_mem, src, src_mem, size, align)
618 enum machine_mode mode = mode_from_align[align];
619 int units = size / align;
620 int remainder = size - units * align;
628 if (remainder && size <= all_from_align[align])
630 most = all_from_align[align] - (align - remainder);
635 most = max_from_align[align];
638 sprintf (entry, "__movstr%s%dx%d",
639 GET_MODE_NAME (mode), most, size - remainder);
640 entry_name = get_identifier (entry);
642 offset_rtx = gen_rtx (CONST_INT, VOIDmode, most - (size - remainder));
644 value_rtx = gen_rtx (MEM, mode,
645 gen_rtx (PLUS, Pmode,
646 gen_rtx (REG, Pmode, 3),
648 RTX_UNCHANGING_P (value_rtx) = RTX_UNCHANGING_P (src_mem);
649 MEM_VOLATILE_P (value_rtx) = MEM_VOLATILE_P (src_mem);
650 MEM_IN_STRUCT_P (value_rtx) = MEM_IN_STRUCT_P (src_mem);
652 value_reg = ((((most - (size - remainder)) / align) & 1) == 0
653 ? (align == 8 ? 6 : 5) : 4);
655 emit_insn (gen_call_block_move
656 (gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)),
657 dest, src, offset_rtx, value_rtx,
658 gen_rtx (REG, GET_MODE (value_rtx), value_reg)));
661 block_move_sequence (gen_rtx (REG, Pmode, 2), dest_mem,
662 gen_rtx (REG, Pmode, 3), src_mem,
663 remainder, align, most);
666 /* Emit code to perform a block move with an offset sequence of ld/st
667 instructions (..., ld 0, st 1, ld 1, st 0, ...). SIZE and ALIGN are
668 known constants. DEST and SRC are registers. OFFSET is the known
669 starting point for the output pattern. */
672 block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset)
680 enum machine_mode mode[2];
685 int offset_ld = offset;
686 int offset_st = offset;
688 active[0] = active[1] = FALSE;
690 /* Establish parameters for the first load and for the second load if
691 it is known to be the same mode as the first. */
692 amount[0] = amount[1] = align;
693 mode[0] = mode_from_align[align];
694 temp[0] = gen_reg_rtx (mode[0]);
695 if (size >= 2 * align)
698 temp[1] = gen_reg_rtx (mode[1]);
709 /* Change modes as the sequence tails off. */
710 if (size < amount[next])
712 amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1));
713 mode[next] = mode_from_align[amount[next]];
714 temp[next] = gen_reg_rtx (mode[next]);
716 size -= amount[next];
717 srcp = gen_rtx (MEM, mode[next],
718 gen_rtx (PLUS, Pmode, src,
719 gen_rtx (CONST_INT, SImode, offset_ld)));
720 RTX_UNCHANGING_P (srcp) = RTX_UNCHANGING_P (src_mem);
721 MEM_VOLATILE_P (srcp) = MEM_VOLATILE_P (src_mem);
722 MEM_IN_STRUCT_P (srcp) = MEM_IN_STRUCT_P (src_mem);
723 emit_move_insn (temp[next], srcp);
724 offset_ld += amount[next];
730 active[phase] = FALSE;
731 dstp = gen_rtx (MEM, mode[phase],
732 gen_rtx (PLUS, Pmode, dest,
733 gen_rtx (CONST_INT, SImode, offset_st)));
734 RTX_UNCHANGING_P (dstp) = RTX_UNCHANGING_P (dest_mem);
735 MEM_VOLATILE_P (dstp) = MEM_VOLATILE_P (dest_mem);
736 MEM_IN_STRUCT_P (dstp) = MEM_IN_STRUCT_P (dest_mem);
737 emit_move_insn (dstp, temp[phase]);
738 offset_st += amount[phase];
741 while (active[next]);
744 /* Emit the code to do an AND operation. */
747 output_and (operands)
752 if (REG_P (operands[2]))
753 return "and %0,%1,%2";
755 value = INTVAL (operands[2]);
756 if (SMALL_INTVAL (value))
757 return "mask %0,%1,%2";
758 else if ((value & 0xffff0000) == 0xffff0000)
759 return "and %0,%1,%x2";
760 else if ((value & 0xffff) == 0xffff)
761 return "and.u %0,%1,%X2";
762 else if ((value & 0xffff) == 0)
763 return "mask.u %0,%1,%X2";
764 else if (integer_ok_for_set (~value))
765 return "clr %0,%1,%S2";
767 return "and.u %0,%1,%X2\n\tand %0,%0,%x2";
770 /* Emit the code to do an inclusive OR operation. */
773 output_ior (operands)
778 if (REG_P (operands[2]))
779 return "or %0,%1,%2";
781 value = INTVAL (operands[2]);
782 if (SMALL_INTVAL (value))
783 return "or %0,%1,%2";
784 else if ((value & 0xffff) == 0)
785 return "or.u %0,%1,%X2";
786 else if (integer_ok_for_set (value))
787 return "set %0,%1,%s2";
789 return "or.u %0,%1,%X2\n\tor %0,%0,%x2";
792 /* Emit the instructions for doing an XOR. */
795 output_xor (operands)
800 if (REG_P (operands[2]))
801 return "xor %0,%1,%2";
803 value = INTVAL (operands[2]);
804 if (SMALL_INTVAL (value))
805 return "xor %0,%1,%2";
806 else if ((value & 0xffff) == 0)
807 return "xor.u %0,%1,%X2";
809 return "xor.u %0,%1,%X2\n\txor %0,%0,%x2";
812 /* Output a call. Normally this is just bsr or jsr, but this also deals with
813 accomplishing a branch after the call by incrementing r1. This requires
814 that various assembler bugs be accommodated. The 4.30 DG/UX assembler
815 requires that forward references not occur when computing the difference of
816 two labels. The [version?] Motorola assembler computes a word difference.
817 No doubt there's more to come!
819 It would seem the same idea could be used to tail call, but in this case,
820 the epilogue will be non-null. */
822 static rtx sb_name = 0;
823 static rtx sb_high = 0;
824 static rtx sb_low = 0;
827 output_call (operands, addr)
837 /* This can be generalized, but there is currently no need. */
838 if (XVECLEN (final_sequence, 0) != 2)
841 /* The address of interior insns is not computed, so use the sequence. */
842 seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
843 jump = XVECEXP (final_sequence, 0, 1);
844 if (GET_CODE (jump) == JUMP_INSN)
848 rtx dest = XEXP (SET_SRC (PATTERN (jump)), 0);
849 int delta = 4 * (insn_addresses[INSN_UID (dest)]
850 - insn_addresses[INSN_UID (seq_insn)]
852 #if (MONITOR_GCC & 0x2) /* How often do long branches happen? */
853 if ((unsigned) (delta + 0x8000) >= 0x10000)
854 warning ("Internal gcc monitor: short-branch(%x)", delta);
857 /* Delete the jump. */
858 PUT_CODE (jump, NOTE);
859 NOTE_LINE_NUMBER (jump) = NOTE_INSN_DELETED;
860 NOTE_SOURCE_FILE (jump) = 0;
862 /* If we loose, we must use the non-delay form. This is unlikely
863 to ever happen. If it becomes a problem, claim that a call
864 has two delay slots and only the second can be filled with
866 #ifdef AS_BUG_IMMEDIATE_LABEL /* The assembler restricts immediate values. */
867 if (! ADD_INTVAL (delta * 2))
869 if (! ADD_INTVAL (delta))
876 ? "bsr %0#plt\n\tbr %l1"
877 : "bsr %0\n\tbr %l1"));
880 /* Output the short branch form. */
881 output_asm_insn ((REG_P (addr)
883 : (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")),
888 ? "subu %#r1,%#r1,.-%l0+4"
889 : "addu %#r1,%#r1,%l0-.-4");
892 operands[0] = gen_label_rtx ();
893 operands[1] = gen_label_rtx ();
898 last = "subu %#r1,%#r1,%l0\n%l1:";
904 last = "addu %#r1,%#r1,%l0\n%l1:";
907 /* Record the values to be computed later as "def name,high-low". */
908 sb_name = gen_rtx (EXPR_LIST, VOIDmode, operands[0], sb_name);
909 sb_high = gen_rtx (EXPR_LIST, VOIDmode, high, sb_high);
910 sb_low = gen_rtx (EXPR_LIST, VOIDmode, low, sb_low);
911 #endif /* Don't USE_GAS */
918 : (flag_pic ? "bsr%. %0#plt" : "bsr%. %0"));
922 output_short_branch_defs (stream)
925 char name[256], high[256], low[256];
927 for (; sb_name && sb_high && sb_low;
928 sb_name = XEXP (sb_name, 1),
929 sb_high = XEXP (sb_high, 1),
930 sb_low = XEXP (sb_low, 1))
932 ASM_GENERATE_INTERNAL_LABEL
933 (name, "L", CODE_LABEL_NUMBER (XEXP (sb_name, 0)));
934 ASM_GENERATE_INTERNAL_LABEL
935 (high, "L", CODE_LABEL_NUMBER (XEXP (sb_high, 0)));
936 ASM_GENERATE_INTERNAL_LABEL
937 (low, "L", CODE_LABEL_NUMBER (XEXP (sb_low, 0)));
938 /* This will change as the assembler requirements become known. */
939 fprintf (stream, "\t%s\t %s,%s-%s\n",
940 SET_ASM_OP, &name[1], &high[1], &low[1]);
942 if (sb_name || sb_high || sb_low)
946 /* Return truth value of the statement that this conditional branch is likely
947 to fall through. CONDITION, is the condition that JUMP_INSN is testing. */
950 mostly_false_jump (jump_insn, condition)
951 rtx jump_insn, condition;
953 rtx target_label = JUMP_LABEL (jump_insn);
956 /* Much of this isn't computed unless we're optimizing. */
960 /* Determine if one path or the other leads to a return. */
961 for (insnt = NEXT_INSN (target_label);
963 insnt = NEXT_INSN (insnt))
965 if (GET_CODE (insnt) == JUMP_INSN)
967 else if (GET_CODE (insnt) == INSN
968 && GET_CODE (PATTERN (insnt)) == SEQUENCE
969 && GET_CODE (XVECEXP (PATTERN (insnt), 0, 0)) == JUMP_INSN)
971 insnt = XVECEXP (PATTERN (insnt), 0, 0);
976 && (GET_CODE (PATTERN (insnt)) == RETURN
977 || (GET_CODE (PATTERN (insnt)) == SET
978 && GET_CODE (SET_SRC (PATTERN (insnt))) == REG
979 && REGNO (SET_SRC (PATTERN (insnt))) == 1)))
982 for (insnj = NEXT_INSN (jump_insn);
984 insnj = NEXT_INSN (insnj))
986 if (GET_CODE (insnj) == JUMP_INSN)
988 else if (GET_CODE (insnj) == INSN
989 && GET_CODE (PATTERN (insnj)) == SEQUENCE
990 && GET_CODE (XVECEXP (PATTERN (insnj), 0, 0)) == JUMP_INSN)
992 insnj = XVECEXP (PATTERN (insnj), 0, 0);
997 && (GET_CODE (PATTERN (insnj)) == RETURN
998 || (GET_CODE (PATTERN (insnj)) == SET
999 && GET_CODE (SET_SRC (PATTERN (insnj))) == REG
1000 && REGNO (SET_SRC (PATTERN (insnj))) == 1)))
1003 /* Predict to not return. */
1004 if ((insnt == 0) != (insnj == 0))
1005 return (insnt == 0);
1007 /* Predict loops to loop. */
1008 for (insnt = PREV_INSN (target_label);
1009 insnt && GET_CODE (insnt) == NOTE;
1010 insnt = PREV_INSN (insnt))
1011 if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_END)
1013 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_BEG)
1015 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_CONT)
1018 /* Predict backward branches usually take. */
1020 insnj = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
1023 if (insn_addresses[INSN_UID (insnj)]
1024 > insn_addresses[INSN_UID (target_label)])
1027 /* EQ tests are usually false and NE tests are usually true. Also,
1028 most quantities are positive, so we can make the appropriate guesses
1029 about signed comparisons against zero. Consider unsigned comparisons
1030 to be a range check and assume quantities to be in range. */
1031 switch (GET_CODE (condition))
1034 /* Unconditional branch. */
1043 case GTU: /* Must get casesi right at least. */
1044 if (XEXP (condition, 1) == const0_rtx)
1051 if (XEXP (condition, 1) == const0_rtx)
1059 /* Return true if the operand is a power of two and is a floating
1060 point type (to optimize division by power of two into multiplication). */
1063 real_power_of_2_operand (op, mode)
1065 enum machine_mode mode;
1069 int i[sizeof (REAL_VALUE_TYPE) / sizeof (int)];
1070 struct { /* IEEE double precision format */
1072 unsigned exponent : 11;
1073 unsigned mantissa1 : 20;
1076 struct { /* IEEE double format to quick check */
1077 unsigned sign : 1; /* if it fits in a float */
1078 unsigned exponent1 : 4;
1079 unsigned exponent2 : 7;
1080 unsigned mantissa1 : 20;
1085 if (GET_MODE (op) != DFmode && GET_MODE (op) != SFmode)
1088 if (GET_CODE (op) != CONST_DOUBLE)
1091 u.i[0] = CONST_DOUBLE_LOW (op);
1092 u.i[1] = CONST_DOUBLE_HIGH (op);
1094 if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0 /* not a power of two */
1095 || u.s.exponent == 0 /* constant 0.0 */
1096 || u.s.exponent == 0x7ff /* NAN */
1097 || (u.s2.exponent1 != 0x8 && u.s2.exponent1 != 0x7))
1098 return 0; /* const won't fit in float */
1103 /* Make OP legitimate for mode MODE. Currently this only deals with DFmode
1104 operands, putting them in registers and making CONST_DOUBLE values
1105 SFmode where possible. */
1108 legitimize_operand (op, mode)
1110 enum machine_mode mode;
1114 union real_extract r;
1115 struct { /* IEEE double precision format */
1117 unsigned exponent : 11;
1118 unsigned mantissa1 : 20;
1121 struct { /* IEEE double format to quick check */
1122 unsigned sign : 1; /* if it fits in a float */
1123 unsigned exponent1 : 4;
1124 unsigned exponent2 : 7;
1125 unsigned mantissa1 : 20;
1130 if (GET_CODE (op) == REG || mode != DFmode)
1133 if (GET_CODE (op) == CONST_DOUBLE)
1135 bcopy (&CONST_DOUBLE_LOW (op), &u.r, sizeof u);
1136 if (u.d.exponent != 0x7ff /* NaN */
1137 && u.d.mantissa2 == 0 /* Mantissa fits */
1138 && (u.s.exponent1 == 0x8 || u.s.exponent1 == 0x7) /* Exponent fits */
1139 && (temp = simplify_unary_operation (FLOAT_TRUNCATE, SFmode,
1141 return gen_rtx (FLOAT_EXTEND, mode, force_reg (SFmode, temp));
1143 else if (register_operand (op, mode))
1146 return force_reg (mode, op);
1149 /* Return true if OP is a suitable input for a move insn. */
1152 move_operand (op, mode)
1154 enum machine_mode mode;
1156 if (register_operand (op, mode))
1158 if (GET_CODE (op) == CONST_INT)
1159 return (classify_integer (mode, INTVAL (op)) < m88k_oru_hi16);
1160 if (GET_MODE (op) != mode)
1162 if (GET_CODE (op) == SUBREG)
1163 op = SUBREG_REG (op);
1164 if (GET_CODE (op) != MEM)
1168 if (GET_CODE (op) == LO_SUM)
1169 return (REG_P (XEXP (op, 0))
1170 && symbolic_address_p (XEXP (op, 1)));
1171 return memory_address_p (mode, op);
1174 /* Return true if OP is suitable for a call insn. */
1177 call_address_operand (op, mode)
1179 enum machine_mode mode;
1181 return (REG_P (op) || symbolic_address_p (op));
1184 /* Returns true if OP is either a symbol reference or a sum of a symbol
1185 reference and a constant. */
1188 symbolic_address_p (op)
1191 switch (GET_CODE (op))
1199 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1200 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1201 && GET_CODE (XEXP (op, 1)) == CONST_INT);
1208 /* Return true if OP is a register or const0_rtx. */
1211 reg_or_0_operand (op, mode)
1213 enum machine_mode mode;
1215 return (op == const0_rtx || register_operand (op, mode));
1218 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
1221 arith_operand (op, mode)
1223 enum machine_mode mode;
1225 return (register_operand (op, mode)
1226 || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
1229 /* Return true if OP is a register or 5 bit integer. */
1232 arith5_operand (op, mode)
1234 enum machine_mode mode;
1236 return (register_operand (op, mode)
1237 || (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32));
1241 arith32_operand (op, mode)
1243 enum machine_mode mode;
1245 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
1249 arith64_operand (op, mode)
1251 enum machine_mode mode;
1253 return (register_operand (op, mode)
1254 || GET_CODE (op) == CONST_INT
1255 || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DImode));
1259 int5_operand (op, mode)
1261 enum machine_mode mode;
1263 return (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32);
1267 int32_operand (op, mode)
1269 enum machine_mode mode;
1271 return (GET_CODE (op) == CONST_INT);
1274 /* Return true if OP is a register or a valid immediate operand for
1278 add_operand (op, mode)
1280 enum machine_mode mode;
1282 return (register_operand (op, mode)
1283 || (GET_CODE (op) == CONST_INT && ADD_INT (op)));
1286 /* Nonzero if this is a bitmask filling the bottom bits, for optimizing and +
1287 shift left combinations into a single mak instruction. */
1293 return (value && POWER_OF_2_or_0 (value + 1));
1297 reg_or_bbx_mask_operand (op, mode)
1299 enum machine_mode mode;
1302 if (register_operand (op, mode))
1304 if (GET_CODE (op) != CONST_INT)
1307 value = INTVAL (op);
1308 if (POWER_OF_2 (value))
1314 /* Return true if OP is valid to use in the context of a floating
1315 point operation. Special case 0.0, since we can use r0. */
1318 real_or_0_operand (op, mode)
1320 enum machine_mode mode;
1322 if (mode != SFmode && mode != DFmode)
1325 return (register_operand (op, mode)
1326 || (GET_CODE (op) == CONST_DOUBLE
1327 && op == CONST0_RTX (mode)));
1330 /* Return true if OP is a relational operator. */
1335 enum machine_mode mode;
1337 switch (GET_CODE (op))
1355 /* Return true if OP is a relational operator, and is not an unsigned
1356 relational operator. */
1359 relop_no_unsigned (op, mode)
1361 enum machine_mode mode;
1363 switch (GET_CODE (op))
1371 /* @@ What is this test doing? Why not use `mode'? */
1372 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
1373 || GET_MODE (op) == DImode
1374 || GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_FLOAT
1375 || GET_MODE (XEXP (op, 0)) == DImode
1376 || GET_MODE_CLASS (GET_MODE (XEXP (op, 1))) == MODE_FLOAT
1377 || GET_MODE (XEXP (op, 1)) == DImode)
1385 /* Return true if the code of this rtx pattern is EQ or NE. */
1388 equality_op (op, mode)
1390 enum machine_mode mode;
1392 return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
1395 /* Return true if the code of this rtx pattern is pc or label_ref. */
1398 pc_or_label_ref (op, mode)
1400 enum machine_mode mode;
1402 return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF);
1405 /* Output to FILE the start of the assembler file. */
1415 output_option (file, sep, type, name, indent, pos, max)
1424 if (strlen (sep) + strlen (type) + strlen (name) + pos > max)
1426 fprintf (file, indent);
1427 return fprintf (file, "%s%s", type, name);
1429 return pos + fprintf (file, "%s%s%s", sep, type, name);
1432 static struct { char *name; int value; } m_options[] = TARGET_SWITCHES;
1435 output_options (file, f_options, f_len, W_options, W_len,
1436 pos, max, sep, indent, term)
1438 struct option *f_options;
1439 struct option *W_options;
1449 pos = output_option (file, sep, "-O", "", indent, pos, max);
1450 if (write_symbols != NO_DEBUG)
1451 pos = output_option (file, sep, "-g", "", indent, pos, max);
1452 if (flag_traditional)
1453 pos = output_option (file, sep, "-traditional", "", indent, pos, max);
1455 pos = output_option (file, sep, "-p", "", indent, pos, max);
1456 if (profile_block_flag)
1457 pos = output_option (file, sep, "-a", "", indent, pos, max);
1459 for (j = 0; j < f_len; j++)
1460 if (*f_options[j].variable == f_options[j].on_value)
1461 pos = output_option (file, sep, "-f", f_options[j].string,
1464 for (j = 0; j < W_len; j++)
1465 if (*W_options[j].variable == W_options[j].on_value)
1466 pos = output_option (file, sep, "-W", W_options[j].string,
1469 for (j = 0; j < sizeof m_options / sizeof m_options[0]; j++)
1470 if (m_options[j].name[0] != '\0'
1471 && m_options[j].value > 0
1472 && ((m_options[j].value & target_flags)
1473 == m_options[j].value))
1474 pos = output_option (file, sep, "-m", m_options[j].name,
1477 if (m88k_short_data)
1478 pos = output_option (file, sep, "-mshort-data-", m88k_short_data,
1481 fprintf (file, term);
1485 output_file_start (file, f_options, f_len, W_options, W_len)
1487 struct option *f_options;
1488 struct option *W_options;
1493 ASM_FIRST_LINE (file);
1494 output_file_directive (file, main_input_filename);
1495 /* Switch to the data section so that the coffsem symbol and the
1496 gcc2_compiled. symbol aren't in the text section. */
1500 pos = fprintf (file, "\n; cc1 (%s) arguments:", VERSION_STRING);
1501 output_options (file, f_options, f_len, W_options, W_len,
1502 pos, 75, " ", "\n; ", "\n\n");
1504 if (TARGET_IDENTIFY_REVISION)
1508 time_t now = time ((time_t *)0);
1509 sprintf (indent, "]\"\n\t%s\t \"@(#)%s [", IDENT_ASM_OP, main_input_filename);
1510 fprintf (file, indent+3);
1511 pos = fprintf (file, "gcc %s, %.24s,", VERSION_STRING, ctime (&now));
1512 output_options (file, f_options, f_len, W_options, W_len,
1513 pos, 150 - strlen (indent), " ", indent, "]\"\n\n");
1517 /* Output an ascii string. */
1520 output_ascii (file, opcode, max, p, size)
1530 register int num = 0;
1532 fprintf (file, "\t%s\t \"", opcode);
1533 for (i = 0; i < size; i++)
1535 register int c = p[i];
1539 fprintf (file, "\"\n\t%s\t \"", opcode);
1543 if (c == '\"' || c == '\\')
1551 else if (in_escape && c >= '0' && c <= '9')
1553 /* If a digit follows an octal-escape, the Vax assembler fails
1554 to stop reading the escape after three digits. Continue to
1555 output the values as an octal-escape until a non-digit is
1557 fprintf (file, "\\%03o", c);
1560 else if (c >= ' ' && c < 0177)
1570 /* Some assemblers can't handle \a, \v, or \?. */
1571 case '\t': c = 't'; goto escape;
1572 case '\f': c = 'f'; goto escape;
1573 case '\b': c = 'b'; goto escape;
1574 case '\r': c = 'r'; goto escape;
1575 case '\n': c = 'n'; goto escape;
1578 fprintf (file, "\\%03o", c);
1583 fprintf (file, "\"\n");
1586 /* Output a label (allows insn-output.c to be compiled without including
1587 m88k.c or needing to include stdio.h). */
1590 output_label (label_number)
1593 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", label_number);
1596 /* Generate the assembly code for function entry.
1598 The prologue is responsible for setting up the stack frame,
1599 initializing the frame pointer register, saving registers that must be
1600 saved, and allocating SIZE additional bytes of storage for the
1601 local variables. SIZE is an integer. FILE is a stdio
1602 stream to which the assembler code should be output.
1604 The label for the beginning of the function need not be output by this
1605 macro. That has already been done when the macro is run.
1607 To determine which registers to save, the macro can refer to the array
1608 `regs_ever_live': element R is nonzero if hard register
1609 R is used anywhere within the function. This implies the
1610 function prologue should save register R, but not if it is one
1611 of the call-used registers.
1613 On machines where functions may or may not have frame-pointers, the
1614 function entry code must vary accordingly; it must set up the frame
1615 pointer if one is wanted, and not otherwise. To determine whether a
1616 frame pointer is in wanted, the macro can refer to the variable
1617 `frame_pointer_needed'. The variable's value will be 1 at run
1618 time in a function that needs a frame pointer.
1620 On machines where an argument may be passed partly in registers and
1621 partly in memory, this macro must examine the variable
1622 `current_function_pretend_args_size', and allocate that many bytes
1623 of uninitialized space on the stack just underneath the first argument
1624 arriving on the stack. (This may not be at the very end of the stack,
1625 if the calling sequence has pushed anything else since pushing the stack
1626 arguments. But usually, on such machines, nothing else has been pushed
1627 yet, because the function prologue itself does all the pushing.)
1629 If `ACCUMULATE_OUTGOING_ARGS' is defined, the variable
1630 `current_function_outgoing_args_size' contains the size in bytes
1631 required for the outgoing arguments. This macro must add that
1632 amount of uninitialized space to very bottom of the stack.
1634 The stack frame we use looks like this:
1637 |==============================================|
1639 |==============================================|
1640 | [caller's outgoing memory arguments] |
1641 |==============================================|
1642 | caller's outgoing argument area (32 bytes) |
1643 sp -> |==============================================| <- ap
1644 | [local variable space] |
1645 |----------------------------------------------|
1646 | [return address (r1)] |
1647 |----------------------------------------------|
1648 | [previous frame pointer (r30)] |
1649 |==============================================| <- fp
1650 | [preserved registers (r25..r14)] |
1651 |----------------------------------------------|
1652 | [preserved registers (x29..x22)] |
1653 |==============================================|
1654 | [dynamically allocated space (alloca)] |
1655 |==============================================|
1656 | [callee's outgoing memory arguments] |
1657 |==============================================|
1658 | [callee's outgoing argument area (32 bytes)] |
1659 |==============================================| <- sp
1663 r1 and r30 must be saved if debugging.
1665 fp (if present) is located two words down from the local
1669 static void emit_add ();
1670 static void preserve_registers ();
1671 static void emit_ldst ();
1672 static void output_tdesc ();
1676 static char save_regs[FIRST_PSEUDO_REGISTER];
1677 static int frame_laid_out;
1678 static int frame_size;
1679 static int variable_args_p;
1680 static int epilogue_marked;
1682 extern char call_used_regs[];
1683 extern int current_function_pretend_args_size;
1684 extern int current_function_outgoing_args_size;
1685 extern int frame_pointer_needed;
1687 #define FIRST_OCS_PRESERVE_REGISTER 14
1688 #define LAST_OCS_PRESERVE_REGISTER 30
1690 #define FIRST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 22)
1691 #define LAST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 31)
1693 #define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
1694 #define ROUND_CALL_BLOCK_SIZE(BYTES) \
1695 (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
1697 /* Establish the position of the FP relative to the SP. This is done
1698 either during FUNCTION_PROLOGUE or by INITIAL_ELIMINATION_OFFSET. */
1701 m88k_layout_frame ()
1707 bzero ((char *) &save_regs[0], sizeof (save_regs));
1708 sp_size = nregs = nxregs = 0;
1709 frame_size = get_frame_size ();
1711 /* Since profiling requires a call, make sure r1 is saved. */
1712 if (profile_flag || profile_block_flag)
1715 /* If we are producing debug information, store r1 and r30 where the
1716 debugger wants to find them (r30 at r30+0, r1 at r30+4). Space has
1717 already been reserved for r1/r30 in STARTING_FRAME_OFFSET. */
1718 if (write_symbols != NO_DEBUG && !TARGET_OCS_FRAME_POSITION)
1721 /* If there is a call, alloca is used, __builtin_alloca is used, or
1722 a dynamic-sized object is defined, add the 8 additional words
1723 for the callee's argument area. The common denominator is that the
1724 FP is required. may_call_alloca only gets calls to alloca;
1725 current_function_calls_alloca gets alloca and __builtin_alloca. */
1726 if (regs_ever_live[1] || frame_pointer_needed)
1729 sp_size += REG_PARM_STACK_SPACE (0);
1732 /* If we are producing PIC, save the addressing base register and r1. */
1733 if (flag_pic && current_function_uses_pic_offset_table)
1735 save_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
1739 /* If a frame is requested, save the previous FP, and the return
1740 address (r1), so that a traceback can be done without using tdesc
1741 information. Otherwise, simply save the FP if it is used as
1742 a preserve register. */
1743 if (frame_pointer_needed)
1744 save_regs[FRAME_POINTER_REGNUM] = save_regs[1] = 1;
1745 else if (regs_ever_live[FRAME_POINTER_REGNUM])
1746 save_regs[FRAME_POINTER_REGNUM] = 1;
1748 /* Figure out which extended register(s) needs to be saved. */
1749 for (regno = FIRST_EXTENDED_REGISTER + 1; regno < FIRST_PSEUDO_REGISTER;
1751 if (regs_ever_live[regno] && ! call_used_regs[regno])
1753 save_regs[regno] = 1;
1757 /* Figure out which normal register(s) needs to be saved. */
1758 for (regno = 2; regno < FRAME_POINTER_REGNUM; regno++)
1759 if (regs_ever_live[regno] && ! call_used_regs[regno])
1761 save_regs[regno] = 1;
1765 /* Achieve greatest use of double memory ops. Either we end up saving
1766 r30 or we use that slot to align the registers we do save. */
1767 if (nregs >= 2 && save_regs[1] && !save_regs[FRAME_POINTER_REGNUM])
1770 nregs += save_regs[1] + save_regs[FRAME_POINTER_REGNUM];
1771 /* if we need to align extended registers, add a word */
1772 if (nxregs > 0 && (nregs & 1) != 0)
1774 sp_size += 4 * nregs;
1775 sp_size += 8 * nxregs;
1776 sp_size += current_function_outgoing_args_size;
1778 /* The first two saved registers are placed above the new frame pointer
1779 if any. In the only case this matters, they are r1 and r30. */
1780 if (frame_pointer_needed || sp_size)
1781 m88k_fp_offset = ROUND_CALL_BLOCK_SIZE (sp_size - STARTING_FRAME_OFFSET);
1783 m88k_fp_offset = -STARTING_FRAME_OFFSET;
1784 m88k_stack_size = m88k_fp_offset + STARTING_FRAME_OFFSET;
1786 /* First, combine m88k_stack_size and size. If m88k_stack_size is
1787 non-zero, align the frame size to 8 mod 16; otherwise align the
1788 frame size to 0 mod 16. (If stacks are 8 byte aligned, this ends
1792 = ((m88k_stack_size ? STACK_UNIT_BOUNDARY - STARTING_FRAME_OFFSET : 0)
1793 - (frame_size % STACK_UNIT_BOUNDARY));
1797 need += STACK_UNIT_BOUNDARY;
1798 (void) assign_stack_local (BLKmode, need, BITS_PER_UNIT);
1799 frame_size = get_frame_size ();
1802 = ROUND_CALL_BLOCK_SIZE (m88k_stack_size + frame_size
1803 + current_function_pretend_args_size);
1807 /* Return true if this function is known to have a null prologue. */
1812 if (! reload_completed)
1814 if (! frame_laid_out)
1815 m88k_layout_frame ();
1816 return (! frame_pointer_needed
1819 && m88k_stack_size == 0);
1822 /* Determine if the current function has any references to the arg pointer.
1823 This is done indirectly by examining the DECL_ARGUMENTS' DECL_RTL.
1824 It is OK to return TRUE if there are no references, but FALSE must be
1832 if (current_function_decl == 0
1833 || current_function_varargs
1837 for (parm = DECL_ARGUMENTS (current_function_decl);
1839 parm = TREE_CHAIN (parm))
1841 if (DECL_RTL (parm) == 0
1842 || GET_CODE (DECL_RTL (parm)) == MEM)
1845 if (DECL_INCOMING_RTL (parm) == 0
1846 || GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
1853 m88k_begin_prologue (stream, size)
1857 epilogue_marked = 0;
1858 m88k_prologue_done = 1; /* it's ok now to put out ln directives */
1862 m88k_end_prologue (stream)
1865 if (TARGET_OCS_DEBUG_INFO)
1866 PUT_OCS_FUNCTION_START (stream);
1867 if (epilogue_marked)
1873 m88k_expand_prologue ()
1875 m88k_layout_frame ();
1877 if (TARGET_OPTIMIZE_ARG_AREA
1879 && ! uses_arg_area_p ())
1881 /* The incoming argument area is used for stack space if it is not
1882 used (or if -mno-optimize-arg-area is given). */
1883 if ((m88k_stack_size -= REG_PARM_STACK_SPACE (0)) < 0)
1884 m88k_stack_size = 0;
1887 if (m88k_stack_size)
1888 emit_add (stack_pointer_rtx, stack_pointer_rtx, -m88k_stack_size);
1890 if (nregs || nxregs)
1891 preserve_registers (m88k_fp_offset + 4, 1);
1893 if (frame_pointer_needed)
1894 emit_add (frame_pointer_rtx, stack_pointer_rtx, m88k_fp_offset);
1896 if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM])
1898 rtx return_reg = gen_rtx (REG, SImode, 1);
1899 rtx label = gen_label_rtx ();
1904 temp_reg = gen_rtx (REG, SImode, TEMP_REGNUM);
1905 emit_move_insn (temp_reg, return_reg);
1907 emit_insn (gen_locate1 (pic_offset_table_rtx, label));
1908 emit_insn (gen_locate2 (pic_offset_table_rtx, label));
1909 emit_insn (gen_addsi3 (pic_offset_table_rtx,
1910 pic_offset_table_rtx, return_reg));
1912 emit_move_insn (return_reg, temp_reg);
1914 if (profile_flag || profile_block_flag)
1915 emit_insn (gen_blockage ());
1918 /* This function generates the assembly code for function exit,
1919 on machines that need it. Args are same as for FUNCTION_PROLOGUE.
1921 The function epilogue should not depend on the current stack pointer!
1922 It should use the frame pointer only, if there is a frame pointer.
1923 This is mandatory because of alloca; we also take advantage of it to
1924 omit stack adjustments before returning. */
1927 m88k_begin_epilogue (stream)
1930 if (TARGET_OCS_DEBUG_INFO)
1931 PUT_OCS_FUNCTION_END (stream);
1932 epilogue_marked = 1;
1936 m88k_end_epilogue (stream, size)
1940 rtx insn = get_last_insn ();
1942 if (TARGET_OCS_DEBUG_INFO && !epilogue_marked)
1943 PUT_OCS_FUNCTION_END (stream);
1945 /* If the last insn isn't a BARRIER, we must write a return insn. This
1946 should only happen if the function has no prologe and no body. */
1947 if (GET_CODE (insn) == NOTE)
1948 insn = prev_nonnote_insn (insn);
1949 if (insn == 0 || GET_CODE (insn) != BARRIER)
1950 fprintf (stream, "\tjmp\t %s\n", reg_names[1]);
1952 output_short_branch_defs (stream);
1954 fprintf (stream, "\n");
1956 if (TARGET_OCS_DEBUG_INFO)
1957 output_tdesc (stream, m88k_fp_offset + 4);
1959 m88k_function_number++;
1960 m88k_prologue_done = 0; /* don't put out ln directives */
1961 variable_args_p = 0; /* has variable args */
1965 m88k_expand_epilogue ()
1967 #if (MONITOR_GCC & 0x4) /* What are interesting prologue/epilogue values? */
1968 fprintf (stream, "; size = %d, m88k_fp_offset = %d, m88k_stack_size = %d\n",
1969 size, m88k_fp_offset, m88k_stack_size);
1972 if (frame_pointer_needed)
1973 emit_add (stack_pointer_rtx, frame_pointer_rtx, -m88k_fp_offset);
1975 if (nregs || nxregs)
1976 preserve_registers (m88k_fp_offset + 4, 0);
1978 if (m88k_stack_size)
1979 emit_add (stack_pointer_rtx, stack_pointer_rtx, m88k_stack_size);
1982 /* Emit insns to set DSTREG to SRCREG + AMOUNT during the prologue or
1986 emit_add (dstreg, srcreg, amount)
1991 rtx incr = gen_rtx (CONST_INT, VOIDmode, abs (amount));
1992 if (! ADD_INTVAL (amount))
1994 rtx temp = gen_rtx (REG, SImode, TEMP_REGNUM);
1995 emit_move_insn (temp, incr);
1998 emit_insn ((amount < 0 ? gen_subsi3 : gen_addsi3) (dstreg, srcreg, incr));
2001 /* Save/restore the preserve registers. base is the highest offset from
2002 r31 at which a register is stored. store_p is true if stores are to
2003 be done; otherwise loads. */
2006 preserve_registers (base, store_p)
2015 } mem_op[FIRST_PSEUDO_REGISTER];
2016 struct mem_op *mo_ptr = mem_op;
2018 /* The 88open OCS mandates that preserved registers be stored in
2019 increasing order. For compatibility with current practice,
2020 the order is r1, r30, then the preserve registers. */
2025 /* An extra word is given in this case to make best use of double
2027 if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM])
2029 emit_ldst (store_p, 1, SImode, offset);
2034 /* Walk the registers to save recording all single memory operations. */
2035 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2036 if (save_regs[regno])
2038 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2041 mo_ptr->regno = regno;
2042 mo_ptr->offset = offset;
2053 /* Walk the registers to save recording all double memory operations.
2054 This avoids a delay in the epilogue (ld.d/ld). */
2056 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2057 if (save_regs[regno])
2059 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2066 mo_ptr->regno = regno-1;
2067 mo_ptr->offset = offset-4;
2074 /* Walk the extended registers to record all memory operations. */
2075 /* Be sure the offset is double word aligned. */
2076 offset = (offset - 1) & ~7;
2077 for (regno = FIRST_PSEUDO_REGISTER - 1; regno > FIRST_EXTENDED_REGISTER;
2079 if (save_regs[regno])
2082 mo_ptr->regno = regno;
2083 mo_ptr->offset = offset;
2090 /* Output the memory operations. */
2091 for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++)
2094 emit_ldst (store_p, mo_ptr->regno,
2095 (mo_ptr->nregs > 1 ? DImode : SImode),
2101 emit_ldst (store_p, regno, mode, offset)
2104 enum machine_mode mode;
2107 rtx reg = gen_rtx (REG, mode, regno);
2108 rtx mem = gen_rtx (MEM, mode, plus_constant (stack_pointer_rtx, offset));
2111 emit_move_insn (mem, reg);
2113 emit_move_insn (reg, mem);
2116 /* Convert the address expression REG to a CFA offset. */
2119 m88k_debugger_offset (reg, offset)
2121 register int offset;
2123 if (GET_CODE (reg) == PLUS)
2125 offset = INTVAL (XEXP (reg, 1));
2126 reg = XEXP (reg, 0);
2129 /* Put the offset in terms of the CFA (arg pointer). */
2130 if (reg == frame_pointer_rtx)
2131 offset += m88k_fp_offset - m88k_stack_size;
2132 else if (reg == stack_pointer_rtx)
2133 offset -= m88k_stack_size;
2134 else if (reg != arg_pointer_rtx)
2136 #if (MONITOR_GCC & 0x10) /* Watch for suspicious symbolic locations. */
2137 if (! (GET_CODE (reg) == REG
2138 && REGNO (reg) >= FIRST_PSEUDO_REGISTER))
2139 warning ("Internal gcc error: Can't express symbolic location");
2147 /* Output the 88open OCS proscribed text description information.
2150 0 22: info-byte-length (16 or 20 bytes)
2151 0 2: info-alignment (word 2)
2152 1 32: info-protocol (version 1 or 2(pic))
2153 2 32: starting-address (inclusive, not counting prologue)
2154 3 32: ending-address (exclusive, not counting epilog)
2155 4 8: info-variant (version 1 or 3(extended registers))
2156 4 17: register-save-mask (from register 14 to 30)
2158 4 1: return-address-info-discriminant
2159 4 5: frame-address-register
2160 5 32: frame-address-offset
2161 6 32: return-address-info
2162 7 32: register-save-offset
2163 8 16: extended-register-save-mask (x16 - x31)
2164 8 16: extended-register-save-offset (WORDS from register-save-offset) */
2167 output_tdesc (file, offset)
2172 long mask, return_address_info, register_save_offset;
2173 long xmask, xregister_save_offset;
2176 for (mask = 0, i = 0, regno = FIRST_OCS_PRESERVE_REGISTER;
2177 regno <= LAST_OCS_PRESERVE_REGISTER;
2181 if (save_regs[regno])
2188 for (xmask = 0, j = 0, regno = FIRST_OCS_EXTENDED_PRESERVE_REGISTER;
2189 regno <= LAST_OCS_EXTENDED_PRESERVE_REGISTER;
2193 if (save_regs[regno])
2202 if ((nxregs > 0 || nregs > 2) && !save_regs[FRAME_POINTER_REGNUM])
2204 return_address_info = - m88k_stack_size + offset;
2205 register_save_offset = return_address_info - i*4;
2209 return_address_info = 1;
2210 register_save_offset = - m88k_stack_size + offset + 4 - i*4;
2213 xregister_save_offset = - (j * 2 + ((register_save_offset >> 2) & 1));
2217 fprintf (file, "\t%s\t %d,%d", INT_ASM_OP, /* 8:0,22:(20 or 16),2:2 */
2218 (((xmask != 0) ? 20 : 16) << 2) | 2,
2221 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_START_PREFIX, m88k_function_number);
2222 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2223 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_END_PREFIX, m88k_function_number);
2224 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2226 fprintf (file, ",0x%x,0x%x,0x%x,0x%x",
2227 /* 8:1,17:0x%.3x,1:0,1:%d,5:%d */
2228 (((xmask ? 3 : 1) << (17+1+1+5))
2230 | ((!!save_regs[1]) << 5)
2231 | (frame_pointer_needed
2232 ? FRAME_POINTER_REGNUM
2233 : STACK_POINTER_REGNUM)),
2234 (m88k_stack_size - (frame_pointer_needed ? m88k_fp_offset : 0)),
2235 return_address_info,
2236 register_save_offset);
2238 fprintf (file, ",0x%x%04x", xmask, (0xffff & xregister_save_offset));
2244 /* Output assembler code to FILE to increment profiler label # LABELNO
2245 for profiling a function entry. NAME is the mcount function name
2246 (varies), SAVEP indicates whether the parameter registers need to
2247 be saved and restored. */
2250 output_function_profiler (file, labelno, name, savep)
2258 char *temp = (savep ? reg_names[2] : reg_names[10]);
2260 /* Remember to update FUNCTION_PROFILER_LENGTH. */
2264 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2265 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2266 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2267 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2268 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2271 ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno);
2274 fprintf (file, "\tor.u\t %s,%s,%shi16(%s#got_rel)\n",
2275 temp, reg_names[0], m88k_pound_sign, &label[1]);
2276 fprintf (file, "\tor\t %s,%s,%slo16(%s#got_rel)\n",
2277 temp, temp, m88k_pound_sign, &label[1]);
2278 sprintf (dbi, "\tld\t %s,%s,%s\n", temp,
2279 reg_names[PIC_OFFSET_TABLE_REGNUM], temp);
2283 sprintf (dbi, "\tld\t %s,%s,%s#got_rel\n", temp,
2284 reg_names[PIC_OFFSET_TABLE_REGNUM], &label[1]);
2288 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n",
2289 temp, reg_names[0], m88k_pound_sign, &label[1]);
2290 sprintf (dbi, "\tor\t %s,%s,%slo16(%s)\n",
2291 temp, temp, m88k_pound_sign, &label[1]);
2295 fprintf (file, "\tbsr.n\t %s#plt\n", name);
2297 fprintf (file, "\tbsr.n\t %s\n", name);
2302 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2303 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2304 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2305 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2306 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2310 /* Output assembler code to FILE to initialize basic-block profiling for
2311 the current module. LABELNO is unique to each instance. */
2314 output_function_block_profiler (file, labelno)
2321 /* Remember to update FUNCTION_BLOCK_PROFILER_LENGTH. */
2323 ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 0);
2324 ASM_GENERATE_INTERNAL_LABEL (label, "LPY", labelno);
2326 /* @@ Need to deal with PIC. I'm not sure what the requirements are on
2327 register usage, so I used r26/r27 to be safe. */
2328 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n", reg_names[27], reg_names[0],
2329 m88k_pound_sign, &block[1]);
2330 fprintf (file, "\tld\t %s,%s,%slo16(%s)\n", reg_names[26], reg_names[27],
2331 m88k_pound_sign, &block[1]);
2332 fprintf (file, "\tbcnd\t %sne0,%s,%s\n",
2333 m88k_pound_sign, reg_names[26], &label[1]);
2334 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2335 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2336 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2337 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2338 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2339 fputs ("\tbsr.n\t ", file);
2340 ASM_OUTPUT_LABELREF (file, "__bb_init_func");
2342 fprintf (file, "\tor\t %s,%s,%slo16(%s)\n", reg_names[2], reg_names[27],
2343 m88k_pound_sign, &block[1]);
2344 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2345 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2346 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2347 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2348 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2349 ASM_OUTPUT_INTERNAL_LABEL (file, "LPY", labelno);
2352 /* Output assembler code to FILE to increment the count associated with
2353 the basic block number BLOCKNO. */
2356 output_block_profiler (file, blockno)
2362 /* Remember to update BLOCK_PROFILER_LENGTH. */
2364 ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 2);
2366 /* @@ Need to deal with PIC. I'm not sure what the requirements are on
2367 register usage, so I used r26/r27 to be safe. */
2368 fprintf (file, "\tor.u\t %s,%s,%shi16(%s+%d)\n", reg_names[27], reg_names[0],
2369 m88k_pound_sign, &block[1], 4 * blockno);
2370 fprintf (file, "\tld\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27],
2371 m88k_pound_sign, &block[1], 4 * blockno);
2372 fprintf (file, "\taddu\t %s,%s,1\n", reg_names[26], reg_names[26]);
2373 fprintf (file, "\tst\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27],
2374 m88k_pound_sign, &block[1], 4 * blockno);
2377 /* Determine whether a function argument is passed in a register, and
2380 The arguments are CUM, which summarizes all the previous
2381 arguments; MODE, the machine mode of the argument; TYPE,
2382 the data type of the argument as a tree node or 0 if that is not known
2383 (which happens for C support library functions); and NAMED,
2384 which is 1 for an ordinary argument and 0 for nameless arguments that
2385 correspond to `...' in the called function's prototype.
2387 The value of the expression should either be a `reg' RTX for the
2388 hard register in which to pass the argument, or zero to pass the
2389 argument on the stack.
2391 On the m88000 the first eight words of args are normally in registers
2392 and the rest are pushed. Double precision floating point must be
2393 double word aligned (and if in a register, starting on an even
2394 register). Structures and unions which are not 4 byte, and word
2395 aligned are passed in memory rather than registers, even if they
2396 would fit completely in the registers under OCS rules.
2398 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2399 For structures that are passed in memory, but could have been
2400 passed in registers, we first load the structure into the
2401 register, and then when the last argument is passed, we store
2402 the registers into the stack locations. This fixes some bugs
2403 where GCC did not expect to have register arguments, followed
2404 by stack arguments, followed by register arguments. */
2407 m88k_function_arg (args_so_far, mode, type, named)
2408 CUMULATIVE_ARGS args_so_far;
2409 enum machine_mode mode;
2415 if (type != 0 /* undo putting struct in register */
2416 && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
2419 if (mode == BLKmode && TARGET_WARN_PASS_STRUCT)
2420 warning ("argument #%d is a structure", args_so_far + 1);
2422 if ((args_so_far & 1) != 0
2423 && (mode == DImode || mode == DFmode
2424 || (type != 0 && TYPE_ALIGN (type) > 32)))
2429 return (rtx) 0; /* don't put args in registers */
2432 if (type == 0 && mode == BLKmode)
2433 abort (); /* m88k_function_arg argument `type' is NULL for BLKmode. */
2435 bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
2436 words = (bytes + 3) / 4;
2438 if (args_so_far + words > 8)
2439 return (rtx) 0; /* args have exhausted registers */
2441 else if (mode == BLKmode
2442 && (TYPE_ALIGN (type) != BITS_PER_WORD
2443 || bytes != UNITS_PER_WORD))
2446 return gen_rtx (REG,
2447 ((mode == BLKmode) ? TYPE_MODE (type) : mode),
2451 /* Do what is necessary for `va_start'. The argument is ignored;
2452 We look at the current function to determine if stdargs or varargs
2453 is used and fill in an initial va_list. A pointer to this constructor
2457 m88k_builtin_saveregs (arglist)
2460 rtx block, addr, argsize;
2461 tree fntype = TREE_TYPE (current_function_decl);
2462 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2463 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2464 != void_type_node)))
2465 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
2467 variable_args_p = 1;
2469 if (CONSTANT_P (current_function_arg_offset_rtx))
2471 fixed = (XINT (current_function_arg_offset_rtx, 0)
2472 + argadj) / UNITS_PER_WORD;
2473 argsize = gen_rtx (CONST_INT, VOIDmode, fixed);
2478 argsize = plus_constant (current_function_arg_offset_rtx, argadj);
2479 argsize = expand_shift (RSHIFT_EXPR, Pmode, argsize,
2480 build_int_2 (2, 0), argsize, 0);
2483 /* Allocate the va_list constructor */
2484 block = assign_stack_local (BLKmode, 3 * UNITS_PER_WORD, BITS_PER_WORD);
2485 RTX_UNCHANGING_P (block) = 1;
2486 RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
2488 /* Store the argsize as the __va_arg member. */
2489 emit_move_insn (change_address (block, SImode, XEXP (block, 0)),
2492 /* Store the arg pointer in the __va_stk member. */
2493 emit_move_insn (change_address (block, Pmode,
2494 plus_constant (XEXP (block, 0),
2496 copy_to_reg (virtual_incoming_args_rtx));
2498 /* Allocate the register space, and store it as the __va_reg member. */
2499 addr = assign_stack_local (BLKmode, 8 * UNITS_PER_WORD, -1);
2500 MEM_IN_STRUCT_P (addr) = 1;
2501 RTX_UNCHANGING_P (addr) = 1;
2502 RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
2503 emit_move_insn (change_address (block, Pmode,
2504 plus_constant (XEXP (block, 0),
2505 2 * UNITS_PER_WORD)),
2506 copy_to_reg (XEXP (addr, 0)));
2508 /* Now store the incoming registers. */
2512 change_address (addr, Pmode,
2513 plus_constant (XEXP (addr, 0),
2514 fixed * UNITS_PER_WORD)),
2517 /* Return the address of the va_list constructor, but don't put it in a
2518 register. This fails when not optimizing and produces worse code when
2520 return XEXP (block, 0);
2523 /* If cmpsi has not been generated, emit code to do the test. Return the
2524 expression describing the test of operator OP. */
2527 emit_test (op, mode)
2529 enum machine_mode mode;
2531 if (m88k_compare_reg == 0)
2532 emit_insn (gen_test (m88k_compare_op0, m88k_compare_op1));
2533 return (gen_rtx (op, mode, m88k_compare_reg, const0_rtx));
2536 /* Determine how to best perform cmpsi/bxx, where cmpsi has a constant
2537 operand. All tests with zero (albeit swapped) and all equality tests
2538 with a constant are done with bcnd. The remaining cases are swapped
2542 emit_bcnd (op, label)
2546 if (m88k_compare_op1 == const0_rtx)
2547 emit_jump_insn (optimize
2548 ? gen_bxx (emit_test (op, VOIDmode), label)
2549 : gen_bcnd (gen_rtx (op, VOIDmode,
2550 m88k_compare_op0, const0_rtx),
2552 else if (m88k_compare_op0 == const0_rtx)
2553 emit_jump_insn (optimize
2554 ? gen_bxx (emit_test (op, VOIDmode), label)
2555 : gen_bcnd (gen_rtx (swap_condition (op), VOIDmode,
2556 m88k_compare_op1, const0_rtx),
2558 else if (op != EQ && op != NE)
2559 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2562 rtx zero = gen_reg_rtx (SImode);
2566 if (GET_CODE (m88k_compare_op1) == CONST_INT)
2568 reg = force_reg (SImode, m88k_compare_op0);
2569 constant = m88k_compare_op1;
2573 reg = force_reg (SImode, m88k_compare_op1);
2574 constant = m88k_compare_op0;
2576 value = INTVAL (constant);
2578 /* Perform an arithmetic computation to make the compared-to value
2579 zero, but avoid loosing if the bcnd is later changed into sxx. */
2580 if (SMALL_INTVAL (value))
2581 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2584 if (SMALL_INTVAL (-value))
2585 emit_insn (gen_addsi3 (zero, reg,
2586 gen_rtx (CONST_INT, VOIDmode, -value)));
2588 emit_insn (gen_xorsi3 (zero, reg, constant));
2590 emit_jump_insn (gen_bcnd (gen_rtx (op, VOIDmode,
2597 /* Print an operand. Recognize special options, documented below. */
2600 print_operand (file, x, code)
2605 enum rtx_code xc = (x ? GET_CODE (x) : UNKNOWN);
2606 register int value = (xc == CONST_INT ? INTVAL (x) : 0);
2607 static int sequencep;
2608 static int reversep;
2612 if (code < 'B' || code > 'E')
2613 output_operand_lossage ("%R not followed by %B/C/D/E");
2615 xc = reverse_condition (xc);
2621 case '*': /* addressing base register for PIC */
2622 fputs (reg_names[PIC_OFFSET_TABLE_REGNUM], file); return;
2624 case '#': /* SVR4 pound-sign syntax character (empty if SVR3) */
2625 fputs (m88k_pound_sign, file); return;
2627 case 'V': /* Output a serializing instruction as needed if the operand
2628 (assumed to be a MEM) is a volatile load. */
2629 case 'v': /* ditto for a volatile store. */
2630 if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE)
2632 /* The m88110 implements two FIFO queues, one for loads and
2633 one for stores. These queues mean that loads complete in
2634 their issue order as do stores. An interaction between the
2635 history buffer and the store reservation station ensures
2636 that a store will not bypass load. Finally, a load will not
2637 bypass store, but only when they reference the same address.
2639 To avoid this reordering (a load bypassing a store) for
2640 volatile references, a serializing instruction is output.
2641 We choose the fldcr instruction as it does not serialize on
2642 the m88100 so that -m88000 code will not be degraded.
2644 The mechanism below is completed by having CC_STATUS_INIT set
2645 the code to the unknown value. */
2647 static rtx last_addr = 0;
2648 if (code == 'V' /* Only need to serialize before a load. */
2649 && m88k_volatile_code != 'V' /* Loads complete in FIFO order. */
2650 && !(m88k_volatile_code == 'v'
2651 && GET_CODE (XEXP (x, 0)) == LO_SUM
2652 && rtx_equal_p (XEXP (XEXP (x, 0), 1), last_addr)))
2653 fprintf (file, "fldcr\t %s,%sfcr63\n\t",
2654 reg_names[0], m88k_pound_sign);
2655 m88k_volatile_code = code;
2656 last_addr = (GET_CODE (XEXP (x, 0)) == LO_SUM
2657 ? XEXP (XEXP (x, 0), 1) : 0);
2661 case 'X': /* print the upper 16 bits... */
2663 case 'x': /* print the lower 16 bits of the integer constant in hex */
2664 if (xc != CONST_INT)
2665 output_operand_lossage ("invalid %x/X value");
2666 fprintf (file, "0x%x", value & 0xffff); return;
2668 case 'H': /* print the low 16 bits of the negated integer constant */
2669 if (xc != CONST_INT)
2670 output_operand_lossage ("invalid %H value");
2672 case 'h': /* print the register or low 16 bits of the integer constant */
2675 if (xc != CONST_INT)
2676 output_operand_lossage ("invalid %h value");
2677 fprintf (file, "%d", value & 0xffff);
2680 case 'Q': /* print the low 8 bits of the negated integer constant */
2681 if (xc != CONST_INT)
2682 output_operand_lossage ("invalid %Q value");
2684 case 'q': /* print the register or low 8 bits of the integer constant */
2687 if (xc != CONST_INT)
2688 output_operand_lossage ("invalid %q value");
2689 fprintf (file, "%d", value & 0xff);
2692 case 'w': /* print the integer constant (X == 32 ? 0 : 32 - X) */
2693 if (xc != CONST_INT)
2694 output_operand_lossage ("invalid %o value");
2695 fprintf (file, "%d", value == 32 ? 0 : 32 - value);
2698 case 'p': /* print the logarithm of the integer constant */
2700 || (value = exact_log2 (value)) < 0)
2701 output_operand_lossage ("invalid %p value");
2702 fprintf (file, "%d", value);
2705 case 'S': /* compliment the value and then... */
2707 case 's': /* print the width and offset values forming the integer
2708 constant with a SET instruction. See integer_ok_for_set. */
2710 register unsigned mask, uval = value;
2711 register int top, bottom;
2713 if (xc != CONST_INT)
2714 output_operand_lossage ("invalid %s/S value");
2715 /* All the "one" bits must be contiguous. If so, MASK will be
2716 a power of two or zero. */
2717 mask = (uval | (uval - 1)) + 1;
2718 if (!(uval && POWER_OF_2_or_0 (mask)))
2719 output_operand_lossage ("invalid %s/S value");
2720 top = mask ? exact_log2 (mask) : 32;
2721 bottom = exact_log2 (uval & ~(uval - 1));
2722 fprintf (file,"%d<%d>", top - bottom, bottom);
2726 case 'P': /* print nothing if pc_rtx; output label_ref */
2727 if (xc == LABEL_REF)
2728 output_addr_const (file, x);
2730 output_operand_lossage ("invalid %P operand");
2733 case 'L': /* print 0 or 1 if operand is label_ref and then... */
2734 fputc (xc == LABEL_REF ? '1' : '0', file);
2735 case '.': /* print .n if delay slot is used */
2736 fputs ((final_sequence
2737 && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
2738 ? ".n\t" : "\t", file);
2741 case 'R': /* reverse the condition of the next print_operand
2742 if operand is a label_ref. */
2744 reversep = (xc == LABEL_REF);
2747 case 'B': /* bcnd branch values */
2748 fputs (m88k_pound_sign, file);
2751 case EQ: fputs ("eq0", file); return;
2752 case NE: fputs ("ne0", file); return;
2753 case GT: fputs ("gt0", file); return;
2754 case LE: fputs ("le0", file); return;
2755 case LT: fputs ("lt0", file); return;
2756 case GE: fputs ("ge0", file); return;
2757 default: output_operand_lossage ("invalid %B value");
2760 case 'C': /* bb0/bb1 branch values for comparisons */
2761 fputs (m88k_pound_sign, file);
2764 case EQ: fputs ("eq", file); return;
2765 case NE: fputs ("ne", file); return;
2766 case GT: fputs ("gt", file); return;
2767 case LE: fputs ("le", file); return;
2768 case LT: fputs ("lt", file); return;
2769 case GE: fputs ("ge", file); return;
2770 case GTU: fputs ("hi", file); return;
2771 case LEU: fputs ("ls", file); return;
2772 case LTU: fputs ("lo", file); return;
2773 case GEU: fputs ("hs", file); return;
2774 default: output_operand_lossage ("invalid %C value");
2777 case 'D': /* bcnd branch values for float comparisons */
2780 case EQ: fputs ("0xa", file); return;
2781 case NE: fputs ("0x5", file); return;
2782 case GT: fputs (m88k_pound_sign, file);
2783 fputs ("gt0", file); return;
2784 case LE: fputs ("0xe", file); return;
2785 case LT: fputs ("0x4", file); return;
2786 case GE: fputs ("0xb", file); return;
2787 default: output_operand_lossage ("invalid %D value");
2790 case 'E': /* bcnd branch values for special integers */
2793 case EQ: fputs ("0x8", file); return;
2794 case NE: fputs ("0x7", file); return;
2795 default: output_operand_lossage ("invalid %E value");
2798 case 'd': /* second register of a two register pair */
2800 output_operand_lossage ("`%d' operand isn't a register");
2801 fputs (reg_names[REGNO (x) + 1], file);
2804 case 'r': /* an immediate 0 should be represented as `r0' */
2805 if (x == const0_rtx)
2807 fputs (reg_names[0], file);
2811 output_operand_lossage ("invalid %r value");
2817 if (REGNO (x) == ARG_POINTER_REGNUM)
2818 output_operand_lossage ("operand is r0");
2820 fputs (reg_names[REGNO (x)], file);
2822 else if (xc == PLUS)
2825 output_address (XEXP (x, 0));
2826 else if (xc == CONST_DOUBLE)
2827 output_operand_lossage ("operand is const_double");
2829 output_addr_const (file, x);
2832 case 'g': /* append #got_rel as needed */
2833 if (flag_pic && (xc == SYMBOL_REF || xc == LABEL_REF))
2835 output_addr_const (file, x);
2836 fputs ("#got_rel", file);
2841 case 'a': /* (standard), assume operand is an address */
2842 case 'c': /* (standard), assume operand is an immediate value */
2843 case 'l': /* (standard), assume operand is a label_ref */
2844 case 'n': /* (standard), like %c, except negate first */
2846 output_operand_lossage ("invalid code");
2851 print_operand_address (file, addr)
2855 register rtx reg0, reg1, temp;
2857 switch (GET_CODE (addr))
2860 if (REGNO (addr) == ARG_POINTER_REGNUM)
2863 fprintf (file, "%s,%s", reg_names[0], reg_names [REGNO (addr)]);
2867 fprintf (file, "%s,%slo16(",
2868 reg_names[REGNO (XEXP (addr, 0))], m88k_pound_sign);
2869 output_addr_const (file, XEXP (addr, 1));
2874 reg0 = XEXP (addr, 0);
2875 reg1 = XEXP (addr, 1);
2876 if (GET_CODE (reg0) == MULT || GET_CODE (reg0) == CONST_INT)
2883 if ((REG_P (reg0) && REGNO (reg0) == ARG_POINTER_REGNUM)
2884 || (REG_P (reg1) && REGNO (reg1) == ARG_POINTER_REGNUM))
2887 else if (REG_P (reg0))
2890 fprintf (file, "%s,%s",
2891 reg_names [REGNO (reg0)], reg_names [REGNO (reg1)]);
2893 else if (GET_CODE (reg1) == CONST_INT)
2894 fprintf (file, "%s,%d",
2895 reg_names [REGNO (reg0)], INTVAL (reg1));
2897 else if (GET_CODE (reg1) == MULT)
2899 rtx mreg = XEXP (reg1, 0);
2900 if (REGNO (mreg) == ARG_POINTER_REGNUM)
2903 fprintf (file, "%s[%s]", reg_names[REGNO (reg0)],
2904 reg_names[REGNO (mreg)]);
2907 else if (GET_CODE (reg1) == ZERO_EXTRACT)
2909 fprintf (file, "%s,%slo16(",
2910 reg_names[REGNO (reg0)], m88k_pound_sign);
2911 output_addr_const (file, XEXP (reg1, 0));
2917 fprintf (file, "%s,", reg_names[REGNO (reg0)]);
2918 output_addr_const (file, reg1);
2919 fputs ("#got_rel", file);
2929 if (REGNO (XEXP (addr, 0)) == ARG_POINTER_REGNUM)
2932 fprintf (file, "%s[%s]",
2933 reg_names[0], reg_names[REGNO (XEXP (addr, 0))]);
2937 fprintf (file, "%s,%shi16(", reg_names[0], m88k_pound_sign);
2938 output_addr_const (file, XEXP (addr, 0));
2943 fprintf (file, "%s,%d", reg_names[0], INTVAL (addr));
2947 fprintf (file, "%s,", reg_names[0]);
2948 if (SHORT_ADDRESS_P (addr, temp))
2950 fprintf (file, "%siw16(", m88k_pound_sign);
2951 output_addr_const (file, addr);
2955 output_addr_const (file, addr);