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. */
24 #include <sys/types.h>
31 #include "hard-reg-set.h"
33 #include "insn-config.h"
34 #include "conditions.h"
35 #include "insn-flags.h"
37 #include "insn-attr.h"
43 extern char *version_string;
44 extern time_t time ();
45 extern char *ctime ();
46 extern int flag_traditional;
47 extern FILE *asm_out_file;
49 static char out_sccs_id[] = "@(#)m88k.c 2.1.11.11 29 May 1992 11:12:23";
50 static char tm_sccs_id [] = TM_SCCS_ID;
52 char *m88k_pound_sign = ""; /* Either # for SVR4 or empty for SVR3 */
53 char *m88k_short_data;
55 int m88k_gp_threshold;
56 int m88k_prologue_done = 0; /* Ln directives can now be emitted */
57 int m88k_function_number = 0; /* Counter unique to each function */
58 int m88k_fp_offset = 0; /* offset of frame pointer if used */
59 int m88k_stack_size = 0; /* size of allocated stack (including frame) */
62 rtx m88k_compare_reg; /* cmp output pseudo register */
63 rtx m88k_compare_op0; /* cmpsi operand 0 */
64 rtx m88k_compare_op1; /* cmpsi operand 1 */
66 enum attr_cpu m88k_cpu; /* target cpu */
68 /* Determine what instructions are needed to manufacture the integer VALUE
72 classify_integer (mode, value)
73 enum machine_mode mode;
80 else if (SMALL_INTVAL (value))
82 else if (SMALL_INTVAL (-value))
84 else if (mode == HImode)
86 else if (mode == QImode)
88 else if ((value & 0xffff) == 0)
90 else if (integer_ok_for_set (value))
97 integer_ok_for_set (value)
98 register unsigned value;
100 /* All the "one" bits must be contiguous. If so, MASK + 1 will be
101 a power of two or zero. */
102 register unsigned mask = (value | (value - 1));
103 return (value && POWER_OF_2_or_0 (mask + 1));
107 output_load_const_int (mode, operands)
108 enum machine_mode mode;
111 static char *patterns[] =
119 "or.u %0,%#r0,%X1\n\tor %0,%0,%x1",
122 if (! REG_P (operands[0])
123 || GET_CODE (operands[1]) != CONST_INT)
125 return patterns[classify_integer (mode, INTVAL (operands[1]))];
128 /* These next two routines assume that floating point numbers are represented
129 in a manner which is consistent between host and target machines. */
132 output_load_const_float (operands)
135 /* These can return 0 under some circumstances when cross-compiling. */
136 operands[0] = operand_subword (operands[0], 0, 0, SFmode);
137 operands[1] = operand_subword (operands[1], 0, 0, SFmode);
139 return output_load_const_int (SImode, operands);
143 output_load_const_double (operands)
148 /* These can return zero on some cross-compilers, but there's nothing
149 we can do about it. */
150 latehalf[0] = operand_subword (operands[0], 1, 0, DFmode);
151 latehalf[1] = operand_subword (operands[1], 1, 0, DFmode);
153 operands[0] = operand_subword (operands[0], 0, 0, DFmode);
154 operands[1] = operand_subword (operands[1], 0, 0, DFmode);
156 output_asm_insn (output_load_const_int (SImode, operands), operands);
158 operands[0] = latehalf[0];
159 operands[1] = latehalf[1];
161 return output_load_const_int (SImode, operands);
165 output_load_const_dimode (operands)
170 latehalf[0] = operand_subword (operands[0], 1, 0, DImode);
171 latehalf[1] = operand_subword (operands[1], 1, 0, DImode);
173 operands[0] = operand_subword (operands[0], 0, 0, DImode);
174 operands[1] = operand_subword (operands[1], 0, 0, DImode);
176 output_asm_insn (output_load_const_int (SImode, operands), operands);
178 operands[0] = latehalf[0];
179 operands[1] = latehalf[1];
181 return output_load_const_int (SImode, operands);
184 /* Emit insns to move operands[1] into operands[0].
186 Return 1 if we have written out everything that needs to be done to
187 do the move. Otherwise, return 0 and the caller will emit the move
191 emit_move_sequence (operands, mode)
193 enum machine_mode mode;
195 register rtx operand0 = operands[0];
196 register rtx operand1 = operands[1];
198 /* Handle most common case first: storing into a register. */
199 if (register_operand (operand0, mode))
201 if (register_operand (operand1, mode)
202 || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
203 || GET_CODE (operand1) == HIGH
204 /* Only `general_operands' can come here, so MEM is ok. */
205 || GET_CODE (operand1) == MEM)
207 /* Run this case quickly. */
208 emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
212 else if (GET_CODE (operand0) == MEM)
214 if (register_operand (operand1, mode)
215 || (operand1 == const0_rtx && GET_MODE_SIZE (mode) <= UNITS_PER_WORD))
217 /* Run this case quickly. */
218 emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
221 if (! reload_in_progress && ! reload_completed)
223 operands[0] = validize_mem (operand0);
224 operands[1] = operand1 = force_reg (mode, operand1);
228 /* Simplify the source if we need to. */
229 if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
231 if (GET_CODE (operand1) != CONST_INT
232 && GET_CODE (operand1) != CONST_DOUBLE)
234 rtx temp = ((reload_in_progress || reload_completed)
235 ? operand0 : gen_reg_rtx (Pmode));
236 operands[1] = legitimize_address (flag_pic
237 && symbolic_address_p (operand1),
240 operands[1] = gen_rtx (SUBREG, mode, operands[1], 0);
244 /* Now have insn-emit do whatever it normally does. */
248 /* Return a legitimate reference for ORIG (either an address or a MEM) using
249 the register REG. If PIC and the address is already position-independent,
253 legitimize_address (pic, orig, reg)
258 rtx addr = (GET_CODE (orig) == MEM ? XEXP (orig, 0) : orig);
264 if (GET_CODE (addr) == SYMBOL_REF
265 || GET_CODE (addr) == LABEL_REF)
267 if (reg == 0) abort ();
271 emit_insn (gen_rtx (SET, VOIDmode,
272 reg, gen_rtx (HIGH, SImode, addr)));
273 emit_insn (gen_rtx (SET, VOIDmode,
274 reg, gen_rtx (LO_SUM, SImode, reg, addr)));
277 new = gen_rtx (MEM, Pmode,
278 gen_rtx (PLUS, SImode,
279 pic_offset_table_rtx, addr));
280 current_function_uses_pic_offset_table = 1;
281 RTX_UNCHANGING_P (new) = 1;
283 rtx insn = emit_move_insn (reg, new);
284 /* Put a REG_EQUAL note on this insn, so that it can be optimized
286 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, orig,
291 else if (GET_CODE (addr) == CONST)
295 if (GET_CODE (XEXP (addr, 0)) == PLUS
296 && XEXP (XEXP (addr, 0), 0) == pic_offset_table_rtx)
302 if (GET_CODE (XEXP (addr, 0)) != PLUS) abort ();
304 base = legitimize_address (1, XEXP (XEXP (addr, 0), 0), reg);
305 addr = legitimize_address (1, XEXP (XEXP (addr, 0), 1),
306 base == reg ? 0 : reg);
308 if (GET_CODE (addr) == CONST_INT)
309 new = plus_constant_for_output (base, INTVAL (addr));
311 new = gen_rtx (PLUS, SImode, base, addr);
312 /* Should we set special REG_NOTEs here? */
315 else if (! SHORT_ADDRESS_P (addr, temp))
317 emit_insn (gen_rtx (SET, VOIDmode,
318 reg, gen_rtx (HIGH, SImode, addr)));
319 new = gen_rtx (LO_SUM, SImode, reg, addr);
323 && GET_CODE (orig) == MEM)
325 new = gen_rtx (MEM, GET_MODE (orig), new);
326 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (orig);
327 MEM_VOLATILE_P (new) = MEM_VOLATILE_P (orig);
328 MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (orig);
333 /* Support functions for code to emit a block move. There are four methods
334 used to perform the block move:
336 + call the looping library function, e.g. __movstrSI64n8
337 + call a non-looping library function, e.g. __movstrHI15x11
338 + produce an inline sequence of ld/st instructions
340 The parameters below describe the library functions produced by
343 #define MOVSTR_LOOP 64 /* __movstrSI64n68 .. __movstrSI64n8 */
344 #define MOVSTR_QI 16 /* __movstrQI16x16 .. __movstrQI16x2 */
345 #define MOVSTR_HI 48 /* __movstrHI48x48 .. __movstrHI48x4 */
346 #define MOVSTR_SI 96 /* __movstrSI96x96 .. __movstrSI96x8 */
347 #define MOVSTR_ODD_SI 48 /* __movstrSI47x47 .. __movstrSI47x11,
348 __movstrSI46x46 .. __movstrSI46x10,
349 __movstrSI45x45 .. __movstrSI45x9 */
350 #define MOVSTR_ODD_HI 16 /* __movstrHI15x15 .. __movstrHI15x5 */
352 /* Break even points where memcpy will do just as well. */
353 #define MOVSTR_QI_LIMIT 13
354 #define MOVSTR_HI_LIMIT 38
355 #define MOVSTR_SI_LIMIT MOVSTR_SI
357 static enum machine_mode mode_from_bytes[] =
358 {VOIDmode, QImode, HImode, VOIDmode, SImode};
359 static int max_from_bytes[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI};
360 static int all_from_bytes[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0, MOVSTR_ODD_SI};
361 static int best_from_bytes[] =
362 {0, MOVSTR_QI_LIMIT, MOVSTR_HI_LIMIT, 0, MOVSTR_SI_LIMIT};
364 static void block_move_loop ();
365 static void block_move_no_loop ();
366 static void block_move_sequence ();
368 /* Emit code to perform a block move. Choose the best method.
370 OPERANDS[0] is the destination.
371 OPERANDS[1] is the source.
372 OPERANDS[2] is the size.
373 OPERANDS[3] is the alignment safe to use. */
376 expand_block_move (dest_mem, src_mem, operands)
381 int align = INTVAL (operands[3]);
382 int constp = (GET_CODE (operands[2]) == CONST_INT);
383 int bytes = (constp ? INTVAL (operands[2]) : 0);
385 if (constp && bytes <= 0)
388 /* Determine machine mode to do move with. */
391 else if (align <= 0 || align == 3)
392 abort (); /* block move invalid alignment. */
394 if (constp && bytes <= 3 * align)
395 block_move_sequence (operands[0], dest_mem, operands[1], src_mem,
398 else if (constp && bytes <= best_from_bytes[align])
399 block_move_no_loop (operands[0], dest_mem, operands[1], src_mem,
402 else if (constp && align == 4)
403 block_move_loop (operands[0], dest_mem, operands[1], src_mem,
408 #ifdef TARGET_MEM_FUNCTIONS
409 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"), 0,
413 operands[2], SImode);
415 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcopy"), 0,
419 operands[2], SImode);
424 /* Emit code to perform a block move by calling a looping movstr library
425 function. SIZE and ALIGN are known constants. DEST and SRC are
429 block_move_loop (dest, dest_mem, src, src_mem, size, align)
435 enum machine_mode mode;
444 /* Determine machine mode to do move with. */
448 /* Determine the structure of the loop. */
449 count = size / MOVSTR_LOOP;
450 units = (size - count * MOVSTR_LOOP) / align;
455 units += MOVSTR_LOOP / align;
460 block_move_no_loop (dest, dest_mem, src, src_mem, size, align);
464 remainder = size - count * MOVSTR_LOOP - units * align;
466 mode = mode_from_bytes[align];
467 sprintf (entry, "__movstr%s%dn%d",
468 GET_MODE_NAME (mode), MOVSTR_LOOP, units * align);
469 entry_name = get_identifier (entry);
471 offset_rtx = gen_rtx (CONST_INT, VOIDmode,
472 MOVSTR_LOOP + (1 - units) * align);
474 value_rtx = gen_rtx (MEM, mode,
475 gen_rtx (PLUS, Pmode,
476 gen_rtx (REG, Pmode, 3),
478 RTX_UNCHANGING_P (value_rtx) = RTX_UNCHANGING_P (src_mem);
479 MEM_VOLATILE_P (value_rtx) = MEM_VOLATILE_P (src_mem);
480 MEM_IN_STRUCT_P (value_rtx) = MEM_IN_STRUCT_P (src_mem);
482 emit_insn (gen_call_block_move_loop
483 (gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)),
484 dest, src, offset_rtx, value_rtx,
485 gen_rtx (REG, GET_MODE (value_rtx), ((units & 1) ? 4 : 5)),
486 gen_rtx (CONST_INT, VOIDmode, count)));
489 block_move_sequence (gen_rtx (REG, Pmode, 2), dest_mem,
490 gen_rtx (REG, Pmode, 3), src_mem,
491 remainder, align, MOVSTR_LOOP + align);
494 /* Emit code to perform a block move by calling a non-looping library
495 function. SIZE and ALIGN are known constants. DEST and SRC are
496 registers. OFFSET is the known starting point for the output pattern. */
499 block_move_no_loop (dest, dest_mem, src, src_mem, size, align)
505 enum machine_mode mode = mode_from_bytes[align];
506 int units = size / align;
507 int remainder = size - units * align;
515 if (remainder && size <= all_from_bytes[align])
517 most = all_from_bytes[align] - (align - remainder);
522 most = max_from_bytes[align];
525 sprintf (entry, "__movstr%s%dx%d",
526 GET_MODE_NAME (mode), most, size - remainder);
527 entry_name = get_identifier (entry);
529 offset_rtx = gen_rtx (CONST_INT, VOIDmode, most - (size - remainder));
531 value_rtx = gen_rtx (MEM, mode,
532 gen_rtx (PLUS, Pmode,
533 gen_rtx (REG, Pmode, 3),
535 RTX_UNCHANGING_P (value_rtx) = RTX_UNCHANGING_P (src_mem);
536 MEM_VOLATILE_P (value_rtx) = MEM_VOLATILE_P (src_mem);
537 MEM_IN_STRUCT_P (value_rtx) = MEM_IN_STRUCT_P (src_mem);
539 evenp = ((most - (size - remainder)) / align) & 1;
541 emit_insn (gen_call_block_move
542 (gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)),
543 dest, src, offset_rtx, value_rtx,
544 gen_rtx (REG, GET_MODE (value_rtx), (evenp ? 4 : 5))));
547 block_move_sequence (gen_rtx (REG, Pmode, 2), dest_mem,
548 gen_rtx (REG, Pmode, 3), src_mem,
549 remainder, align, most);
552 /* Emit code to perform a block move with an offset sequence of ld/st
553 instructions (..., ld 0, st 1, ld 1, st 0, ...). SIZE and ALIGN are
554 known constants. DEST and SRC are registers. OFFSET is the known
555 starting point for the output pattern. */
558 block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset)
566 enum machine_mode mode[2];
571 int offset_ld = offset;
572 int offset_st = offset;
574 active[0] = active[1] = FALSE;
576 /* Establish parameters for the first load and for the second load if
577 it is known to be the same mode as the first. */
578 amount[0] = amount[1] = align;
579 mode[0] = mode_from_bytes[align];
580 temp[0] = gen_reg_rtx (mode[0]);
581 if (size >= 2 * align)
584 temp[1] = gen_reg_rtx (mode[1]);
595 /* Change modes as the sequence tails off. */
596 if (size < amount[next])
598 amount[next] = (size >= 2 ? 2 : 1);
599 mode[next] = mode_from_bytes[amount[next]];
600 temp[next] = gen_reg_rtx (mode[next]);
602 size -= amount[next];
603 srcp = gen_rtx (MEM, mode[next],
604 gen_rtx (PLUS, Pmode, src,
605 gen_rtx (CONST_INT, SImode, offset_ld)));
606 RTX_UNCHANGING_P (srcp) = RTX_UNCHANGING_P (src_mem);
607 MEM_VOLATILE_P (srcp) = MEM_VOLATILE_P (src_mem);
608 MEM_IN_STRUCT_P (srcp) = MEM_IN_STRUCT_P (src_mem);
609 emit_move_insn (temp[next], srcp);
610 offset_ld += amount[next];
616 active[phase] = FALSE;
617 dstp = gen_rtx (MEM, mode[phase],
618 gen_rtx (PLUS, Pmode, dest,
619 gen_rtx (CONST_INT, SImode, offset_st)));
620 RTX_UNCHANGING_P (dstp) = RTX_UNCHANGING_P (dest_mem);
621 MEM_VOLATILE_P (dstp) = MEM_VOLATILE_P (dest_mem);
622 MEM_IN_STRUCT_P (dstp) = MEM_IN_STRUCT_P (dest_mem);
623 emit_move_insn (dstp, temp[phase]);
624 offset_st += amount[phase];
627 while (active[next]);
630 /* Emit the code to do an AND operation. */
633 output_and (operands)
638 if (REG_P (operands[2]))
639 return "and %0,%1,%2";
641 value = INTVAL (operands[2]);
642 if (SMALL_INTVAL (value))
643 return "mask %0,%1,%2";
644 else if ((value & 0xffff0000) == 0xffff0000)
645 return "and %0,%1,%x2";
646 else if ((value & 0xffff) == 0xffff)
647 return "and.u %0,%1,%X2";
648 else if ((value & 0xffff) == 0)
649 return "mask.u %0,%1,%X2";
650 else if (integer_ok_for_set (~value))
651 return "clr %0,%1,%S2";
653 return "and.u %0,%1,%X2\n\tand %0,%0,%x2";
656 /* Emit the code to do an inclusive OR operation. */
659 output_ior (operands)
664 if (REG_P (operands[2]))
665 return "or %0,%1,%2";
667 value = INTVAL (operands[2]);
668 if (SMALL_INTVAL (value))
669 return "or %0,%1,%2";
670 else if ((value & 0xffff) == 0)
671 return "or.u %0,%1,%X2";
672 else if (integer_ok_for_set (value))
673 return "set %0,%1,%s2";
675 return "or.u %0,%1,%X2\n\tor %0,%0,%x2";
678 /* Emit the instructions for doing an XOR. */
681 output_xor (operands)
686 if (REG_P (operands[2]))
687 return "xor %0,%1,%2";
689 value = INTVAL (operands[2]);
690 if (SMALL_INTVAL (value))
691 return "xor %0,%1,%2";
692 else if ((value & 0xffff) == 0)
693 return "xor.u %0,%1,%X2";
695 return "xor.u %0,%1,%X2\n\txor %0,%0,%x2";
698 /* Output a call. Normally this is just bsr or jsr, but this also deals with
699 accomplishing a branch after the call by incrementing r1. This requires
700 that various assembler bugs be accommodated. The 4.30 DG/UX assembler
701 requires that forward references not occur when computing the difference of
702 two labels. The [version?] Motorola assembler computes a word difference.
703 No doubt there's more to come!
705 It would seem the same idea could be used to tail call, but in this case,
706 the epilogue will be non-null. */
708 static rtx sb_name = 0;
709 static rtx sb_high = 0;
710 static rtx sb_low = 0;
713 output_call (operands, addr)
723 /* This can be generalized, but there is currently no need. */
724 if (XVECLEN (final_sequence, 0) != 2)
727 /* The address of interior insns is not computed, so use the sequence. */
728 seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
729 jump = XVECEXP (final_sequence, 0, 1);
730 if (GET_CODE (jump) == JUMP_INSN)
734 rtx dest = XEXP (SET_SRC (PATTERN (jump)), 0);
735 int delta = 4 * (insn_addresses[INSN_UID (dest)]
736 - insn_addresses[INSN_UID (seq_insn)]
738 #if (MONITOR_GCC & 0x2) /* How often do long branches happen? */
739 if ((unsigned) (delta + 0x8000) >= 0x10000)
740 warning ("Internal gcc monitor: short-branch(%x)", delta);
743 /* Delete the jump. */
744 PUT_CODE (jump, NOTE);
745 NOTE_LINE_NUMBER (jump) = NOTE_INSN_DELETED;
746 NOTE_SOURCE_FILE (jump) = 0;
748 /* If we loose, we must use the non-delay form. This is unlikely
749 to ever happen. If it becomes a problem, claim that a call
750 has two delay slots and only the second can be filled with
752 #ifdef AS_BUG_IMMEDIATE_LABEL /* The assembler restricts immediate values. */
753 if (! ADD_INTVAL (delta * 2))
755 if (! ADD_INTVAL (delta))
762 ? "bsr %0#plt\n\tbr %l1"
763 : "bsr %0\n\tbr %l1"));
766 /* Output the short branch form. */
767 output_asm_insn ((REG_P (addr)
769 : (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")),
772 operands[0] = gen_label_rtx ();
773 operands[1] = gen_label_rtx ();
778 last = "subu %#r1,%#r1,%l0\n%l1:";
784 last = "addu %#r1,%#r1,%l0\n%l1:";
787 /* Record the values to be computed later as "def name,high-low". */
788 sb_name = gen_rtx (EXPR_LIST, VOIDmode, operands[0], sb_name);
789 sb_high = gen_rtx (EXPR_LIST, VOIDmode, high, sb_high);
790 sb_low = gen_rtx (EXPR_LIST, VOIDmode, low, sb_low);
797 : (flag_pic ? "bsr%. %0#plt" : "bsr%. %0"));
801 output_short_branch_defs (stream)
804 char name[256], high[256], low[256];
806 for (; sb_name && sb_high && sb_low;
807 sb_name = XEXP (sb_name, 1),
808 sb_high = XEXP (sb_high, 1),
809 sb_low = XEXP (sb_low, 1))
811 ASM_GENERATE_INTERNAL_LABEL
812 (name, "L", CODE_LABEL_NUMBER (XEXP (sb_name, 0)));
813 ASM_GENERATE_INTERNAL_LABEL
814 (high, "L", CODE_LABEL_NUMBER (XEXP (sb_high, 0)));
815 ASM_GENERATE_INTERNAL_LABEL
816 (low, "L", CODE_LABEL_NUMBER (XEXP (sb_low, 0)));
817 /* This will change as the assembler requirements become known. */
818 fprintf (stream, "\t%s\t %s,%s-%s\n",
819 SET_ASM_OP, &name[1], &high[1], &low[1]);
821 if (sb_name || sb_high || sb_low)
825 /* Return truth value of the statement that this conditional branch is likely
826 to fall through. CONDITION, is the condition that JUMP_INSN is testing. */
829 mostly_false_jump (jump_insn, condition)
830 rtx jump_insn, condition;
832 rtx target_label = JUMP_LABEL (jump_insn);
835 /* Much of this isn't computed unless we're optimizing. */
839 /* Determine if one path or the other leads to a return. */
840 for (insnt = NEXT_INSN (target_label);
842 insnt = NEXT_INSN (insnt))
844 if (GET_CODE (insnt) == JUMP_INSN)
846 else if (GET_CODE (insnt) == SEQUENCE
847 && GET_CODE (XVECEXP (insnt, 0, 0)) == JUMP_INSN)
849 insnt = XVECEXP (insnt, 0, 0);
854 && (GET_CODE (PATTERN (insnt)) == RETURN
855 || (GET_CODE (PATTERN (insnt)) == SET
856 && GET_CODE (SET_SRC (PATTERN (insnt))) == REG
857 && REGNO (SET_SRC (PATTERN (insnt))) == 1)))
860 for (insnj = NEXT_INSN (jump_insn);
862 insnj = NEXT_INSN (insnj))
864 if (GET_CODE (insnj) == JUMP_INSN)
866 else if (GET_CODE (insnj) == SEQUENCE
867 && GET_CODE (XVECEXP (insnj, 0, 0)) == JUMP_INSN)
869 insnj = XVECEXP (insnj, 0, 0);
874 && (GET_CODE (PATTERN (insnj)) == RETURN
875 || (GET_CODE (PATTERN (insnj)) == SET
876 && GET_CODE (SET_SRC (PATTERN (insnj))) == REG
877 && REGNO (SET_SRC (PATTERN (insnj))) == 1)))
880 /* Predict to not return. */
881 if ((insnt == 0) != (insnj == 0))
884 /* Predict loops to loop. */
885 for (insnt = PREV_INSN (target_label);
886 insnt && GET_CODE (insnt) == NOTE;
887 insnt = PREV_INSN (insnt))
888 if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_END)
890 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_BEG)
892 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_CONT)
895 /* Predict backward branches usually take. */
897 insnj = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
900 if (insn_addresses[INSN_UID (insnj)]
901 > insn_addresses[INSN_UID (target_label)])
904 /* EQ tests are usually false and NE tests are usually true. Also,
905 most quantities are positive, so we can make the appropriate guesses
906 about signed comparisons against zero. Consider unsigned comparisons
907 to be a range check and assume quantities to be in range. */
908 switch (GET_CODE (condition))
911 /* Unconditional branch. */
920 case GTU: /* Must get casesi right at least. */
921 if (XEXP (condition, 1) == const0_rtx)
928 if (XEXP (condition, 1) == const0_rtx)
936 /* Return true if the operand is a power of two and is a floating
937 point type (to optimize division by power of two into multiplication). */
940 real_power_of_2_operand (op, mode)
942 enum machine_mode mode;
946 int i[sizeof (REAL_VALUE_TYPE) / sizeof (int)];
947 struct { /* IEEE double precision format */
949 unsigned exponent : 11;
950 unsigned mantissa1 : 20;
953 struct { /* IEEE double format to quick check */
954 unsigned sign : 1; /* if it fits in a float */
955 unsigned exponent1 : 4;
956 unsigned exponent2 : 7;
957 unsigned mantissa1 : 20;
962 if (GET_MODE (op) != DFmode && GET_MODE (op) != SFmode)
965 if (GET_CODE (op) != CONST_DOUBLE)
968 u.i[0] = CONST_DOUBLE_LOW (op);
969 u.i[1] = CONST_DOUBLE_HIGH (op);
971 if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0 /* not a power of two */
972 || u.s.exponent == 0 /* constant 0.0 */
973 || u.s.exponent == 0x7ff /* NAN */
974 || (u.s2.exponent1 != 0x8 && u.s2.exponent1 != 0x7))
975 return 0; /* const won't fit in float */
980 /* Make OP legitimate for mode MODE. Currently this only deals with DFmode
981 operands, putting them in registers and making CONST_DOUBLE values
982 SFmode where possible. */
985 legitimize_operand (op, mode)
987 enum machine_mode mode;
991 union real_extract r;
992 struct { /* IEEE double precision format */
994 unsigned exponent : 11;
995 unsigned mantissa1 : 20;
998 struct { /* IEEE double format to quick check */
999 unsigned sign : 1; /* if it fits in a float */
1000 unsigned exponent1 : 4;
1001 unsigned exponent2 : 7;
1002 unsigned mantissa1 : 20;
1007 if (GET_CODE (op) == REG || mode != DFmode)
1010 if (GET_CODE (op) == CONST_DOUBLE)
1012 bcopy (&CONST_DOUBLE_LOW (op), &u.r, sizeof u);
1013 if (u.d.exponent != 0x7ff /* NaN */
1014 && u.d.mantissa2 == 0 /* Mantissa fits */
1015 && (u.s.exponent1 == 0x8 || u.s.exponent1 == 0x7) /* Exponent fits */
1016 && (temp = simplify_unary_operation (FLOAT_TRUNCATE, SFmode,
1018 return gen_rtx (FLOAT_EXTEND, mode, force_reg (SFmode, temp));
1020 else if (register_operand (op, mode))
1023 return force_reg (mode, op);
1026 /* Return true if OP is a suitable input for a move insn. */
1029 move_operand (op, mode)
1031 enum machine_mode mode;
1033 if (register_operand (op, mode))
1035 if (GET_CODE (op) == CONST_INT)
1036 return (classify_integer (mode, INTVAL (op)) < m88k_oru_hi16);
1037 if (GET_MODE (op) != mode)
1039 if (GET_CODE (op) == SUBREG)
1040 op = SUBREG_REG (op);
1041 if (GET_CODE (op) != MEM)
1045 if (GET_CODE (op) == LO_SUM)
1046 return (REG_P (XEXP (op, 0))
1047 && symbolic_address_p (XEXP (op, 1)));
1048 return memory_address_p (mode, op);
1051 /* Return true if OP is suitable for a call insn. */
1054 call_address_operand (op, mode)
1056 enum machine_mode mode;
1058 return (REG_P (op) || symbolic_address_p (op));
1061 /* Returns true if OP is either a symbol reference or a sum of a symbol
1062 reference and a constant. */
1065 symbolic_address_p (op)
1068 switch (GET_CODE (op))
1076 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1077 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1078 && GET_CODE (XEXP (op, 1)) == CONST_INT);
1085 /* Return true if OP is a register or const0_rtx. */
1088 reg_or_0_operand (op, mode)
1090 enum machine_mode mode;
1092 return (op == const0_rtx || register_operand (op, mode));
1095 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
1098 arith_operand (op, mode)
1100 enum machine_mode mode;
1102 return (register_operand (op, mode)
1103 || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
1106 /* Return true if OP is a register or 5 bit integer. */
1109 arith5_operand (op, mode)
1111 enum machine_mode mode;
1113 return (register_operand (op, mode)
1114 || (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32));
1118 arith32_operand (op, mode)
1120 enum machine_mode mode;
1122 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
1126 arith64_operand (op, mode)
1128 enum machine_mode mode;
1130 return (register_operand (op, mode)
1131 || GET_CODE (op) == CONST_INT
1132 || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DImode));
1136 int5_operand (op, mode)
1138 enum machine_mode mode;
1140 return (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32);
1144 int32_operand (op, mode)
1146 enum machine_mode mode;
1148 return (GET_CODE (op) == CONST_INT);
1151 /* Return true if OP is a register or a valid immediate operand for
1155 add_operand (op, mode)
1157 enum machine_mode mode;
1159 return (register_operand (op, mode)
1160 || (GET_CODE (op) == CONST_INT && ADD_INT (op)));
1163 /* Nonzero if this is a bitmask filling the bottom bits, for optimizing and +
1164 shift left combinations into a single mak instruction. */
1170 return (value && POWER_OF_2_or_0 (value + 1));
1174 reg_or_bbx_mask_operand (op, mode)
1176 enum machine_mode mode;
1179 if (register_operand (op, mode))
1181 if (GET_CODE (op) != CONST_INT)
1184 value = INTVAL (op);
1185 if (POWER_OF_2 (value))
1191 /* Return true if OP is valid to use in the context of a floating
1192 point operation. Special case 0.0, since we can use r0. */
1195 real_or_0_operand (op, mode)
1197 enum machine_mode mode;
1199 if (mode != SFmode && mode != DFmode)
1202 return (register_operand (op, mode)
1203 || (GET_CODE (op) == CONST_DOUBLE
1204 && op == CONST0_RTX (mode)));
1207 /* Return true if OP is a relational operator. */
1212 enum machine_mode mode;
1214 switch (GET_CODE (op))
1232 /* Return true if OP is a relational operator, and is not an unsigned
1233 relational operator. */
1236 relop_no_unsigned (op, mode)
1238 enum machine_mode mode;
1240 switch (GET_CODE (op))
1248 /* @@ What is this test doing? Why not use `mode'? */
1249 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
1250 || GET_MODE (op) == DImode
1251 || GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_FLOAT
1252 || GET_MODE (XEXP (op, 0)) == DImode
1253 || GET_MODE_CLASS (GET_MODE (XEXP (op, 1))) == MODE_FLOAT
1254 || GET_MODE (XEXP (op, 1)) == DImode)
1262 /* Return true if the code of this rtx pattern is EQ or NE. */
1265 equality_op (op, mode)
1267 enum machine_mode mode;
1269 return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
1272 /* Return true if the code of this rtx pattern is pc or label_ref. */
1275 pc_or_label_ref (op, mode)
1277 enum machine_mode mode;
1279 return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF);
1282 /* Output to FILE the start of the assembler file. */
1292 output_option (file, sep, type, name, indent, pos, max)
1301 if (strlen (sep) + strlen (type) + strlen (name) + pos > max)
1303 fprintf (file, indent);
1304 return fprintf (file, "%s%s", type, name);
1306 return pos + fprintf (file, "%s%s%s", sep, type, name);
1309 static struct { char *name; int value; } m_options[] = TARGET_SWITCHES;
1312 output_options (file, f_options, f_len, W_options, W_len,
1313 pos, max, sep, indent, term)
1315 struct option *f_options;
1316 struct option *W_options;
1326 pos = output_option (file, sep, "-O", "", indent, pos, max);
1327 if (write_symbols != NO_DEBUG)
1328 pos = output_option (file, sep, "-g", "", indent, pos, max);
1329 if (flag_traditional)
1330 pos = output_option (file, sep, "-traditional", "", indent, pos, max);
1332 pos = output_option (file, sep, "-p", "", indent, pos, max);
1333 if (profile_block_flag)
1334 pos = output_option (file, sep, "-a", "", indent, pos, max);
1336 for (j = 0; j < f_len; j++)
1337 if (*f_options[j].variable == f_options[j].on_value)
1338 pos = output_option (file, sep, "-f", f_options[j].string,
1341 for (j = 0; j < W_len; j++)
1342 if (*W_options[j].variable == W_options[j].on_value)
1343 pos = output_option (file, sep, "-W", W_options[j].string,
1346 for (j = 0; j < sizeof m_options / sizeof m_options[0]; j++)
1347 if (m_options[j].name[0] != '\0'
1348 && m_options[j].value > 0
1349 && ((m_options[j].value & target_flags)
1350 == m_options[j].value))
1351 pos = output_option (file, sep, "-m", m_options[j].name,
1354 if (m88k_short_data)
1355 pos = output_option (file, sep, "-mshort-data-", m88k_short_data,
1358 fprintf (file, term);
1362 output_file_start (file, f_options, f_len, W_options, W_len)
1364 struct option *f_options;
1365 struct option *W_options;
1370 ASM_FIRST_LINE (file);
1371 output_file_directive (file, main_input_filename);
1372 /* Switch to the data section so that the coffsem symbol and the
1373 gcc2_compiled. symbol aren't in the text section. */
1377 pos = fprintf (file, "\n; cc1 (%s) arguments:", VERSION_STRING);
1378 output_options (file, f_options, f_len, W_options, W_len,
1379 pos, 75, " ", "\n; ", "\n\n");
1381 if (TARGET_IDENTIFY_REVISION)
1385 time_t now = time ((time_t *)0);
1386 sprintf (indent, "]\"\n\t%s\t \"@(#)%s [", IDENT_ASM_OP, main_input_filename);
1387 fprintf (file, indent+3);
1388 pos = fprintf (file, "gcc %s, %.24s,", VERSION_STRING, ctime (&now));
1389 output_options (file, f_options, f_len, W_options, W_len,
1390 pos, 150 - strlen (indent), " ", indent, "]\"\n\n");
1394 /* Output an ascii string. */
1397 output_ascii (file, opcode, max, p, size)
1406 register int num = 0;
1408 fprintf (file, "\t%s\t \"", opcode);
1409 for (i = 0; i < size; i++)
1411 register int c = p[i];
1415 fprintf (file, "\"\n\t%s\t \"", opcode);
1419 if (c == '\"' || c == '\\')
1425 if (c >= ' ' && c < 0177)
1432 fprintf (file, "\\%03o", c);
1434 /* After an octal-escape, if a digit follows,
1435 terminate one string constant and start another.
1436 The Vax assembler fails to stop reading the escape
1437 after three digits, so this is the only way we
1438 can get it to parse the data properly. */
1439 if (i < size - 1 && p[i + 1] >= '0' && p[i + 1] <= '9')
1440 num = max + 1; /* next pass will start a new string */
1443 fprintf (file, "\"\n");
1446 /* Output a label (allows insn-output.c to be compiled without including
1447 m88k.c or needing to include stdio.h). */
1450 output_label (label_number)
1453 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", label_number);
1456 /* Handle a pragma directive. HANDLE_PRAGMA conspires to parse the input
1457 following #pragma into tokens based on yylex. */
1460 m88k_handle_pragma_token (string, token)
1464 static enum pragma_state
1477 if (HANDLE_PRAGMA_WEAK)
1481 if (state == ps_name || state == ps_value)
1483 fprintf (asm_out_file, "\t%s\t ", WEAK_ASM_OP);
1484 ASM_OUTPUT_LABELREF (asm_out_file, name);
1485 fputc ('\n', asm_out_file);
1486 if (state == ps_value)
1488 fprintf (asm_out_file, "\t%s\t ", SET_ASM_OP);
1489 ASM_OUTPUT_LABELREF (asm_out_file, name);
1490 fputc (',', asm_out_file);
1491 ASM_OUTPUT_LABELREF (asm_out_file, value);
1492 fputc ('\n', asm_out_file);
1495 else if (! (state == ps_done || state == ps_start))
1496 warning ("ignoring malformed #pragma weak symbol [=value]");
1504 && TREE_CODE (token) == IDENTIFIER_NODE
1505 && !strcmp (IDENTIFIER_POINTER (token), "weak"))
1513 && TREE_CODE (token) == IDENTIFIER_NODE)
1515 name = IDENTIFIER_POINTER (token);
1523 state = (strcmp (string, "=") ? ps_bad : ps_equals);
1528 && TREE_CODE (token) == IDENTIFIER_NODE)
1530 value = IDENTIFIER_POINTER (token);
1549 /* Generate the assembly code for function entry.
1551 The prologue is responsible for setting up the stack frame,
1552 initializing the frame pointer register, saving registers that must be
1553 saved, and allocating SIZE additional bytes of storage for the
1554 local variables. SIZE is an integer. FILE is a stdio
1555 stream to which the assembler code should be output.
1557 The label for the beginning of the function need not be output by this
1558 macro. That has already been done when the macro is run.
1560 To determine which registers to save, the macro can refer to the array
1561 `regs_ever_live': element R is nonzero if hard register
1562 R is used anywhere within the function. This implies the
1563 function prologue should save register R, but not if it is one
1564 of the call-used registers.
1566 On machines where functions may or may not have frame-pointers, the
1567 function entry code must vary accordingly; it must set up the frame
1568 pointer if one is wanted, and not otherwise. To determine whether a
1569 frame pointer is in wanted, the macro can refer to the variable
1570 `frame_pointer_needed'. The variable's value will be 1 at run
1571 time in a function that needs a frame pointer.
1573 On machines where an argument may be passed partly in registers and
1574 partly in memory, this macro must examine the variable
1575 `current_function_pretend_args_size', and allocate that many bytes
1576 of uninitialized space on the stack just underneath the first argument
1577 arriving on the stack. (This may not be at the very end of the stack,
1578 if the calling sequence has pushed anything else since pushing the stack
1579 arguments. But usually, on such machines, nothing else has been pushed
1580 yet, because the function prologue itself does all the pushing.)
1582 If `ACCUMULATE_OUTGOING_ARGS' is defined, the variable
1583 `current_function_outgoing_args_size' contains the size in bytes
1584 required for the outgoing arguments. This macro must add that
1585 amount of uninitialized space to very bottom of the stack.
1587 The stack frame we use looks like this:
1590 |==============================================|
1592 |==============================================|
1593 | [caller's outgoing memory arguments] |
1594 |==============================================|
1595 | caller's outgoing argument area (32 bytes) |
1596 sp -> |==============================================| <- ap
1597 | [local variable space] |
1598 |----------------------------------------------|
1599 | [return address (r1)] |
1600 |----------------------------------------------|
1601 | [previous frame pointer (r30)] |
1602 |==============================================| <- fp
1603 | [preserved registers (r25..r14)] |
1604 |----------------------------------------------|
1605 | [preserved registers (x29..x22)] |
1606 |==============================================|
1607 | [dynamically allocated space (alloca)] |
1608 |==============================================|
1609 | [callee's outgoing memory arguments] |
1610 |==============================================|
1611 | [callee's outgoing argument area (32 bytes)] |
1612 |==============================================| <- sp
1616 r1 and r30 must be saved if debugging.
1618 fp (if present) is located two words down from the local
1622 static void output_reg_adjust ();
1623 static void preserve_registers ();
1624 static void output_tdesc ();
1628 static char save_regs[FIRST_PSEUDO_REGISTER];
1629 static int frame_laid_out;
1630 static int frame_size;
1631 static int variable_args_p;
1633 extern char call_used_regs[];
1634 extern int current_function_pretend_args_size;
1635 extern int current_function_outgoing_args_size;
1636 extern int frame_pointer_needed;
1638 #define FIRST_OCS_PRESERVE_REGISTER 14
1639 #define LAST_OCS_PRESERVE_REGISTER 30
1641 #define FIRST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 22)
1642 #define LAST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 31)
1644 #define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
1645 #define ROUND_CALL_BLOCK_SIZE(BYTES) \
1646 (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
1648 /* Establish the position of the FP relative to the SP. This is done
1649 either during FUNCTION_PROLOGUE or by INITIAL_ELIMINATION_OFFSET. */
1652 m88k_layout_frame ()
1658 bzero ((char *) &save_regs[0], sizeof (save_regs));
1659 sp_size = nregs = nxregs = 0;
1660 frame_size = get_frame_size ();
1662 /* Since profiling requires a call, make sure r1 is saved. */
1663 if (profile_flag || profile_block_flag)
1666 /* If we are producing debug information, store r1 and r30 where the
1667 debugger wants to find them (r30 at r30+0, r1 at r30+4). Space has
1668 already been reserved for r1/r30 in STARTING_FRAME_OFFSET. */
1669 if (write_symbols != NO_DEBUG && !TARGET_OCS_FRAME_POSITION)
1672 /* If there is a call, alloca is used, __builtin_alloca is used, or
1673 a dynamic-sized object is defined, add the 8 additional words
1674 for the callee's argument area. The common denominator is that the
1675 FP is required. may_call_alloca only gets calls to alloca;
1676 current_function_calls_alloca gets alloca and __builtin_alloca. */
1677 if (regs_ever_live[1] || frame_pointer_needed)
1680 sp_size += REG_PARM_STACK_SPACE (0);
1683 /* If we are producing PIC, save the addressing base register and r1. */
1684 if (flag_pic && current_function_uses_pic_offset_table)
1686 save_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
1690 /* If a frame is requested, save the previous FP, and the return
1691 address (r1), so that a traceback can be done without using tdesc
1692 information. Otherwise, simply save the FP if it is used as
1693 a preserve register. */
1694 if (frame_pointer_needed)
1695 save_regs[FRAME_POINTER_REGNUM] = save_regs[1] = 1;
1696 else if (regs_ever_live[FRAME_POINTER_REGNUM])
1697 save_regs[FRAME_POINTER_REGNUM] = 1;
1699 /* Figure out which extended register(s) needs to be saved. */
1700 for (regno = FIRST_EXTENDED_REGISTER + 1; regno < FIRST_PSEUDO_REGISTER;
1702 if (regs_ever_live[regno] && ! call_used_regs[regno])
1704 save_regs[regno] = 1;
1708 /* Figure out which normal register(s) needs to be saved. */
1709 for (regno = 2; regno < FRAME_POINTER_REGNUM; regno++)
1710 if (regs_ever_live[regno] && ! call_used_regs[regno])
1712 save_regs[regno] = 1;
1716 /* Achieve greatest use of double memory ops. Either we end up saving
1717 r30 or we use that slot to align the registers we do save. */
1718 if (nregs >= 2 && save_regs[1] && !save_regs[FRAME_POINTER_REGNUM])
1721 nregs += save_regs[1] + save_regs[FRAME_POINTER_REGNUM];
1722 /* if we need to align extended registers, add a word */
1723 if (nxregs > 0 && (nregs & 1) != 0)
1725 sp_size += 4 * nregs;
1726 sp_size += 8 * nxregs;
1727 sp_size += current_function_outgoing_args_size;
1729 /* The first two saved registers are placed above the new frame pointer
1730 if any. In the only case this matters, they are r1 and r30. */
1731 if (frame_pointer_needed || sp_size)
1732 m88k_fp_offset = ROUND_CALL_BLOCK_SIZE (sp_size - STARTING_FRAME_OFFSET);
1734 m88k_fp_offset = -STARTING_FRAME_OFFSET;
1735 m88k_stack_size = m88k_fp_offset + STARTING_FRAME_OFFSET;
1737 /* First, combine m88k_stack_size and size. If m88k_stack_size is
1738 non-zero, align the frame size to 8 mod 16; otherwise align the
1739 frame size to 0 mod 16. (If stacks are 8 byte aligned, this ends
1743 = ((m88k_stack_size ? STACK_UNIT_BOUNDARY - STARTING_FRAME_OFFSET : 0)
1744 - (frame_size % STACK_UNIT_BOUNDARY));
1748 need += STACK_UNIT_BOUNDARY;
1749 (void) assign_stack_local (BLKmode, need, BITS_PER_UNIT);
1750 frame_size = get_frame_size ();
1753 = ROUND_CALL_BLOCK_SIZE (m88k_stack_size + frame_size
1754 + current_function_pretend_args_size);
1758 /* Return true if this function is known to have a null epilogue. */
1763 if (! reload_completed)
1765 if (! frame_laid_out)
1766 m88k_layout_frame ();
1767 return (! frame_pointer_needed
1770 && m88k_stack_size == 0);
1773 /* Determine the number of instructions needed for the function epilogue. */
1775 #define MAX_EPILOGUE_DELAY_INSNS 4
1777 static char epilogue_dead_regs[FIRST_PSEUDO_REGISTER];
1779 delay_slots_for_epilogue ()
1781 register int insns = save_regs[1] + save_regs[FRAME_POINTER_REGNUM];
1782 register int regs = nregs - insns;
1785 insns += 1 + (regs & 1);
1786 else if (nregs == 4)
1787 /* This is a special cases of ld/ld/ld.d which has no start-up delay. */
1792 bzero ((char *) &epilogue_dead_regs[0], sizeof (epilogue_dead_regs));
1793 epilogue_dead_regs[1] = save_regs[1];
1794 epilogue_dead_regs[STACK_POINTER_REGNUM] = frame_pointer_needed;
1795 epilogue_dead_regs[TEMP_REGNUM] = ! ADD_INTVAL (m88k_fp_offset);
1801 /* Return 1 if X is safe to use as an epilogue insn. */
1804 ok_for_epilogue_p (x)
1810 switch (GET_CODE (x))
1813 for (i = REGNO (x), j = i + HARD_REGNO_NREGS (i, GET_MODE (x));
1816 if (epilogue_dead_regs[i])
1830 fmt = GET_RTX_FORMAT (GET_CODE (x));
1831 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
1835 if (!ok_for_epilogue_p (XEXP (x, i)))
1838 else if (fmt[i] == 'E')
1840 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1841 if (!ok_for_epilogue_p (XVECEXP (x, i, j)))
1849 eligible_for_epilogue_delay (insn)
1852 switch (get_attr_type (insn))
1858 return ok_for_epilogue_p (PATTERN (insn));
1864 /* Determine if the current function has any references to the arg pointer.
1865 This is done indirectly by examining the DECL_ARGUMENTS' DECL_RTL.
1866 It is OK to return TRUE if there are no references, but FALSE must be
1874 if (current_function_decl == 0
1875 || current_function_varargs
1879 for (parm = DECL_ARGUMENTS (current_function_decl);
1881 parm = TREE_CHAIN (parm))
1883 if (DECL_RTL (parm) == 0
1884 || GET_CODE (DECL_RTL (parm)) == MEM)
1887 if (DECL_INCOMING_RTL (parm) == 0
1888 || GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
1895 m88k_output_prologue (stream, size)
1899 int old_fp_offset = m88k_fp_offset;
1900 int old_stack_size = m88k_stack_size;
1902 m88k_layout_frame ();
1903 #if (MONITOR_GCC & 0x8) /* Watch for suspicious register elimination changes. */
1904 if (frame_laid_out > 1)
1906 if (old_fp_offset != m88k_fp_offset)
1907 warning ("Internal gcc error: FP offset has changed by %d bytes",
1908 m88k_fp_offset - old_fp_offset);
1909 if (old_stack_size != m88k_stack_size)
1910 warning ("Internal gcc error: stack size has changed by %d bytes",
1911 m88k_stack_size - old_stack_size);
1916 if (TARGET_OPTIMIZE_ARG_AREA
1918 && ! uses_arg_area_p ())
1920 /* The incoming argument area is used for stack space if it is not
1921 used (or if -mno-use-arg-area is given). */
1922 if ((m88k_stack_size -= REG_PARM_STACK_SPACE (0)) < 0)
1923 m88k_stack_size = 0;
1926 if (m88k_stack_size)
1927 output_reg_adjust (stream, 31, 31, -m88k_stack_size, 0);
1929 if (nregs || nxregs)
1930 preserve_registers (stream, m88k_fp_offset + 4, 1);
1932 if (frame_pointer_needed)
1933 output_reg_adjust (stream, 30, 31, m88k_fp_offset, 0);
1935 if (TARGET_OCS_DEBUG_INFO)
1936 PUT_OCS_FUNCTION_START (stream);
1938 if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM])
1943 fprintf (stream, "\tor\t %s,%s,0\n",
1944 reg_names[TEMP_REGNUM], reg_names[1]);
1945 ASM_GENERATE_INTERNAL_LABEL (label, "Lab", m88k_function_number);
1946 fprintf (stream, "\tbsr.n\t %s\n", &label[1]);
1947 fprintf (stream, "\tor.u\t %s,%s,%shi16(%s#abdiff)\n",
1948 reg_names[PIC_OFFSET_TABLE_REGNUM], reg_names[0],
1949 m88k_pound_sign, &label[1]);
1950 ASM_OUTPUT_INTERNAL_LABEL (stream, "Lab", m88k_function_number);
1951 fprintf (stream, "\tor\t %s,%s,%slo16(%s#abdiff)\n",
1952 reg_names[PIC_OFFSET_TABLE_REGNUM],
1953 reg_names[PIC_OFFSET_TABLE_REGNUM],
1954 m88k_pound_sign, &label[1]);
1955 fprintf (stream, "\taddu\t %s,%s,%s\n",
1956 reg_names[PIC_OFFSET_TABLE_REGNUM],
1957 reg_names[PIC_OFFSET_TABLE_REGNUM], reg_names[1]);
1959 fprintf (stream, "\tor\t %s,%s,0\n",
1960 reg_names[1], reg_names[TEMP_REGNUM]);
1963 m88k_prologue_done = 1; /* it's ok now to put out ln directives */
1966 /* This function generates the assembly code for function exit,
1967 on machines that need it. Args are same as for FUNCTION_PROLOGUE.
1969 The function epilogue should not depend on the current stack pointer!
1970 It should use the frame pointer only, if there is a frame pointer.
1971 This is mandatory because of alloca; we also take advantage of it to
1972 omit stack adjustments before returning. */
1975 m88k_output_epilogue (stream, size)
1979 rtx insn = get_last_insn ();
1980 #if (MONITOR_GCC & 0x4) /* What are interesting prologue/epilogue values? */
1981 fprintf (stream, "; size = %d, m88k_fp_offset = %d, m88k_stack_size = %d\n",
1982 size, m88k_fp_offset, m88k_stack_size);
1985 output_short_branch_defs (stream);
1987 if (TARGET_OCS_DEBUG_INFO)
1988 PUT_OCS_FUNCTION_END (stream);
1990 /* If the last insn was a BARRIER, we don't have to write any code. */
1991 if (GET_CODE (insn) == NOTE)
1992 insn = prev_nonnote_insn (insn);
1993 if (insn && GET_CODE (insn) == BARRIER)
1995 if (current_function_epilogue_delay_list)
2000 if (frame_pointer_needed)
2001 output_reg_adjust (stream, 31, 30, -m88k_fp_offset, 0);
2003 if (nregs || nxregs)
2004 preserve_registers (stream, m88k_fp_offset + 4, 0);
2006 output_reg_adjust (stream, 31, 31, m88k_stack_size, 1);
2009 fprintf (stream, "\n");
2011 if (TARGET_OCS_DEBUG_INFO)
2012 output_tdesc (stream, m88k_fp_offset + 4);
2014 m88k_function_number++;
2015 m88k_prologue_done = 0; /* don't put out ln directives */
2016 variable_args_p = 0; /* has variable args */
2019 /* Output code to STREAM to set DSTREG to SRCREG + AMOUNT. Issue
2020 a return instruction and use it's delay slot based on RETURN_P. */
2023 output_reg_adjust (stream, dstreg, srcreg, amount, return_p)
2025 int dstreg, srcreg, amount, return_p;
2038 if (amount == 0 && dstreg == srcreg)
2041 fprintf (stream, "\tjmp\t %s\n", reg_names[1]);
2044 else if (SMALL_INTVAL (amount))
2045 sprintf (incr, "\t%s\t %s,%s,%d", opname,
2046 reg_names[dstreg], reg_names[srcreg], amount);
2051 operands[0] = gen_rtx (REG, SImode, TEMP_REGNUM);
2052 operands[1] = gen_rtx (CONST_INT, VOIDmode, amount);
2053 output_asm_insn (output_load_const_int (SImode, operands),
2055 sprintf (incr, "\t%s\t %s,%s,%s", opname,
2056 reg_names[dstreg], reg_names[srcreg], reg_names[TEMP_REGNUM]);
2060 fprintf (stream, "%s\n", incr);
2061 else if (flag_delayed_branch)
2062 fprintf (stream, "\tjmp.n\t %s\n%s\n", reg_names[1], incr);
2064 fprintf (stream, "%s\n\tjmp\t %s\n", incr, reg_names[1]);
2067 /* Save/restore the preserve registers. base is the highest offset from
2068 r31 at which a register is stored. store_p is true if stores are to
2069 be done; otherwise loads. When loading, output the epilogue delay
2073 preserve_registers (stream, base, store_p)
2079 char *fmt = (store_p ? "\tst%s\t %s,%s,%d\n" : "\tld%s\t %s,%s,%d\n");
2084 } mem_op[FIRST_PSEUDO_REGISTER];
2085 struct mem_op *mo_ptr = mem_op;
2087 /* The 88open OCS mandates that preserved registers be stored in
2088 increasing order. For compatibility with current practice,
2089 the order is r1, r30, then the preserve registers. */
2094 /* An extra word is given in this case to make best use of double
2096 if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM])
2098 fprintf (stream, fmt, "", reg_names[1], reg_names[31], offset);
2103 /* Walk the registers to save recording all single memory operations. */
2104 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2105 if (save_regs[regno])
2107 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2110 mo_ptr->regno = regno;
2111 mo_ptr->offset = offset;
2122 /* Walk the registers to save recording all double memory operations.
2123 This avoids a delay in the epilogue (ld.d/ld). */
2125 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2126 if (save_regs[regno])
2128 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2135 mo_ptr->regno = regno-1;
2136 mo_ptr->offset = offset-4;
2143 /* Walk the extended registers to record all memory operations. */
2144 /* Be sure the offset is double word aligned. */
2145 offset = (offset - 1) & ~7;
2146 for (regno = FIRST_PSEUDO_REGISTER - 1; regno > FIRST_EXTENDED_REGISTER;
2148 if (save_regs[regno])
2151 mo_ptr->regno = regno;
2152 mo_ptr->offset = offset;
2159 /* Output the delay insns interleaved with the memory operations. */
2160 if (! store_p && current_function_epilogue_delay_list)
2162 rtx delay_insns = current_function_epilogue_delay_list;
2165 /* The first delay insn goes after the restore of r1. */
2168 final_scan_insn (XEXP (delay_insns, 0), stream, 1, 0, 1);
2169 delay_insns = XEXP (delay_insns, 1);
2174 /* Find a memory operation that doesn't conflict with this insn. */
2175 for (mo_ptr = mem_op; mo_ptr->regno != 0; mo_ptr++)
2179 int nregs = (mo_ptr->regno < FIRST_EXTENDED_REGISTER
2180 ? mo_ptr->nregs : 1);
2181 rtx ok_insns = delay_insns;
2184 for (i = 0; i < nregs; i++)
2185 epilogue_dead_regs[mo_ptr->regno + i] = 1;
2189 insn = XEXP (ok_insns, 0);
2190 ok_insns = XEXP (ok_insns, 1);
2192 if (! ok_for_epilogue_p (PATTERN (insn)))
2194 for (i = 0; i < nregs; i++)
2195 epilogue_dead_regs[mo_ptr->regno + i] = 0;
2197 break; /* foreach delay insn */
2202 fprintf (stream, fmt, mo_ptr->nregs > 1 ? ".d" : "",
2203 reg_names[mo_ptr->regno], reg_names[31],
2206 break; /* foreach memory operation */
2210 final_scan_insn (XEXP (delay_insns, 0), stream, 1, 0, 1);
2211 delay_insns = XEXP (delay_insns, 1);
2215 /* Output the memory operations. */
2216 for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++)
2219 fprintf (stream, fmt, mo_ptr->nregs > 1 ? ".d" : "",
2220 reg_names[mo_ptr->regno], reg_names[31], mo_ptr->offset);
2224 /* Convert the address expression REG to a CFA offset. */
2227 m88k_debugger_offset (reg, offset)
2229 register int offset;
2231 if (GET_CODE (reg) == PLUS)
2233 offset = INTVAL (XEXP (reg, 1));
2234 reg = XEXP (reg, 0);
2237 /* Put the offset in terms of the CFA (arg pointer). */
2238 if (reg == frame_pointer_rtx)
2239 offset += m88k_fp_offset - m88k_stack_size;
2240 else if (reg == stack_pointer_rtx)
2241 offset -= m88k_stack_size;
2242 else if (reg != arg_pointer_rtx)
2244 #if (MONITOR_GCC & 0x10) /* Watch for suspicious symbolic locations. */
2245 if (! (GET_CODE (reg) == REG
2246 && REGNO (reg) >= FIRST_PSEUDO_REGISTER))
2247 warning ("Internal gcc error: Can't express symbolic location");
2255 /* Output the 88open OCS proscribed text description information.
2258 0 22: info-byte-length (16 or 20 bytes)
2259 0 2: info-alignment (word 2)
2260 1 32: info-protocol (version 1 or 2(pic))
2261 2 32: starting-address (inclusive, not counting prologue)
2262 3 32: ending-address (exclusive, not counting epilog)
2263 4 8: info-variant (version 1 or 3(extended registers))
2264 4 17: register-save-mask (from register 14 to 30)
2266 4 1: return-address-info-discriminant
2267 4 5: frame-address-register
2268 5 32: frame-address-offset
2269 6 32: return-address-info
2270 7 32: register-save-offset
2271 8 16: extended-register-save-mask (x16 - x31)
2272 8 16: extended-register-save-offset (WORDS from register-save-offset) */
2275 output_tdesc (file, offset)
2280 long mask, return_address_info, register_save_offset;
2281 long xmask, xregister_save_offset;
2284 for (mask = 0, i = 0, regno = FIRST_OCS_PRESERVE_REGISTER;
2285 regno <= LAST_OCS_PRESERVE_REGISTER;
2289 if (save_regs[regno])
2296 for (xmask = 0, j = 0, regno = FIRST_OCS_EXTENDED_PRESERVE_REGISTER;
2297 regno <= LAST_OCS_EXTENDED_PRESERVE_REGISTER;
2301 if (save_regs[regno])
2310 if ((nxregs > 0 || nregs > 2) && !save_regs[FRAME_POINTER_REGNUM])
2312 return_address_info = - m88k_stack_size + offset;
2313 register_save_offset = return_address_info - i*4;
2317 return_address_info = 1;
2318 register_save_offset = - m88k_stack_size + offset + 4 - i*4;
2321 xregister_save_offset = - (j * 2 + ((register_save_offset >> 2) & 1));
2325 fprintf (file, "\t%s\t %d,%d", INT_ASM_OP, /* 8:0,22:(20 or 16),2:2 */
2326 (((xmask != 0) ? 20 : 16) << 2) | 2,
2329 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_START_PREFIX, m88k_function_number);
2330 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2331 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_END_PREFIX, m88k_function_number);
2332 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2334 fprintf (file, ",0x%x,0x%x,0x%x,0x%x",
2335 /* 8:1,17:0x%.3x,1:0,1:%d,5:%d */
2336 (((xmask ? 3 : 1) << (17+1+1+5))
2338 | ((!!save_regs[1]) << 5)
2339 | (frame_pointer_needed
2340 ? FRAME_POINTER_REGNUM
2341 : STACK_POINTER_REGNUM)),
2342 (m88k_stack_size - (frame_pointer_needed ? m88k_fp_offset : 0)),
2343 return_address_info,
2344 register_save_offset);
2346 fprintf (file, ",0x%x%04x", xmask, (0xffff & xregister_save_offset));
2352 /* Output assembler code to FILE to increment profiler label # LABELNO
2353 for profiling a function entry. NAME is the mcount function name
2354 (varies), SAVEP indicates whether the parameter registers need to
2355 be saved and restored. */
2358 output_function_profiler (file, labelno, name, savep)
2366 char *temp = (savep ? reg_names[2] : reg_names[10]);
2370 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2371 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2372 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2373 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2374 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2377 ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno);
2380 fprintf (file, "\tor.u\t %s,%s,%shi16(%s#got_rel)\n",
2381 temp, reg_names[0], m88k_pound_sign, &label[1]);
2382 fprintf (file, "\tor\t %s,%s,%slo16(%s#got_rel)\n",
2383 temp, temp, m88k_pound_sign, &label[1]);
2384 sprintf (dbi, "\tld\t %s,%s,%s\n", temp,
2385 reg_names[PIC_OFFSET_TABLE_REGNUM], temp);
2389 sprintf (dbi, "\tld\t %s,%s,%s#got_rel\n", temp,
2390 reg_names[PIC_OFFSET_TABLE_REGNUM], &label[1]);
2394 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n",
2395 temp, reg_names[0], m88k_pound_sign, &label[1]);
2396 sprintf (dbi, "\tor\t %s,%s,%slo16(%s)\n",
2397 temp, temp, m88k_pound_sign, &label[1]);
2401 fprintf (file, "\tbsr.n\t %s#plt\n", name);
2403 fprintf (file, "\tbsr.n\t %s\n", name);
2408 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2409 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2410 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2411 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2412 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2416 /* Output assembler code to FILE to initialize basic-block profiling for
2417 the current module. LABELNO is unique to each instance. */
2420 output_function_block_profiler (file, labelno)
2427 ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 0);
2428 ASM_GENERATE_INTERNAL_LABEL (label, "LPY", labelno);
2430 /* @@ Need to deal with PIC. I'm not sure what the requirements are on
2431 register usage, so I used r26/r27 to be safe. */
2432 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n", reg_names[27], reg_names[0],
2433 m88k_pound_sign, &block[1]);
2434 fprintf (file, "\tld\t %s,%s,%slo16(%s)\n", reg_names[26], reg_names[27],
2435 m88k_pound_sign, &block[1]);
2436 fprintf (file, "\tbcnd\t %sne0,%s,%s\n",
2437 m88k_pound_sign, reg_names[26], &label[1]);
2438 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2439 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2440 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2441 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2442 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2443 fputs ("\tbsr.n\t ", file);
2444 ASM_OUTPUT_LABELREF (file, "__bb_init_func");
2446 fprintf (file, "\tor\t %s,%s,%slo16(%s)\n", reg_names[2], reg_names[27],
2447 m88k_pound_sign, &block[1]);
2448 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2449 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2450 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2451 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2452 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2453 ASM_OUTPUT_INTERNAL_LABEL (file, "LPY", labelno);
2456 /* Output assembler code to FILE to increment the count associated with
2457 the basic block number BLOCKNO. */
2460 output_block_profiler (file, blockno)
2466 ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 2);
2468 /* @@ Need to deal with PIC. I'm not sure what the requirements are on
2469 register usage, so I used r26/r27 to be safe. */
2470 fprintf (file, "\tor.u\t %s,%s,%shi16(%s+%d)\n", reg_names[27], reg_names[0],
2471 m88k_pound_sign, &block[1], 4 * blockno);
2472 fprintf (file, "\tld\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27],
2473 m88k_pound_sign, &block[1], 4 * blockno);
2474 fprintf (file, "\taddu\t %s,%s,1\n", reg_names[26], reg_names[26]);
2475 fprintf (file, "\tst\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27],
2476 m88k_pound_sign, &block[1], 4 * blockno);
2479 /* Determine whether a function argument is passed in a register, and
2482 The arguments are CUM, which summarizes all the previous
2483 arguments; MODE, the machine mode of the argument; TYPE,
2484 the data type of the argument as a tree node or 0 if that is not known
2485 (which happens for C support library functions); and NAMED,
2486 which is 1 for an ordinary argument and 0 for nameless arguments that
2487 correspond to `...' in the called function's prototype.
2489 The value of the expression should either be a `reg' RTX for the
2490 hard register in which to pass the argument, or zero to pass the
2491 argument on the stack.
2493 On the m88000 the first eight words of args are normally in registers
2494 and the rest are pushed. Double precision floating point must be
2495 double word aligned (and if in a register, starting on an even
2496 register). Structures and unions which are not 4 byte, and word
2497 aligned are passed in memory rather than registers, even if they
2498 would fit completely in the registers under OCS rules.
2500 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2501 For structures that are passed in memory, but could have been
2502 passed in registers, we first load the structure into the
2503 register, and then when the last argument is passed, we store
2504 the registers into the stack locations. This fixes some bugs
2505 where GCC did not expect to have register arguments, followed
2506 by stack arguments, followed by register arguments. */
2509 m88k_function_arg (args_so_far, mode, type, named)
2510 CUMULATIVE_ARGS args_so_far;
2511 enum machine_mode mode;
2517 if (type != 0 /* undo putting struct in register */
2518 && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
2521 if (mode == BLKmode && TARGET_WARN_PASS_STRUCT)
2522 warning ("argument #%d is a structure", args_so_far + 1);
2524 if ((args_so_far & 1) != 0
2525 && (mode == DImode || mode == DFmode
2526 || (type != 0 && TYPE_ALIGN (type) > 32)))
2531 return (rtx) 0; /* don't put args in registers */
2534 if (type == 0 && mode == BLKmode)
2535 abort (); /* m88k_function_arg argument `type' is NULL for BLKmode. */
2537 bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
2538 words = (bytes + 3) / 4;
2540 if (args_so_far + words > 8)
2541 return (rtx) 0; /* args have exhausted registers */
2543 else if (mode == BLKmode
2544 && (TYPE_ALIGN (type) != BITS_PER_WORD
2545 || bytes != UNITS_PER_WORD))
2548 return gen_rtx (REG,
2549 ((mode == BLKmode) ? TYPE_MODE (type) : mode),
2553 /* Do what is necessary for `va_start'. The argument is ignored;
2554 We look at the current function to determine if stdargs or varargs
2555 is used and fill in an initial va_list. A pointer to this constructor
2559 m88k_builtin_saveregs (arglist)
2562 rtx block, addr, argsize;
2563 tree fntype = TREE_TYPE (current_function_decl);
2564 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2565 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2566 != void_type_node)))
2567 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
2569 variable_args_p = 1;
2571 if (CONSTANT_P (current_function_arg_offset_rtx))
2573 fixed = (XINT (current_function_arg_offset_rtx, 0)
2574 + argadj) / UNITS_PER_WORD;
2575 argsize = gen_rtx (CONST_INT, VOIDmode, fixed);
2580 argsize = plus_constant (current_function_arg_offset_rtx, argadj);
2581 argsize = expand_shift (RSHIFT_EXPR, Pmode, argsize,
2582 build_int_2 (2, 0), argsize, 0);
2585 /* Allocate the va_list constructor */
2586 block = assign_stack_local (BLKmode, 3 * UNITS_PER_WORD, BITS_PER_WORD);
2587 RTX_UNCHANGING_P (block) = 1;
2588 RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
2590 /* Store the argsize as the __va_arg member. */
2591 emit_move_insn (change_address (block, SImode, XEXP (block, 0)),
2594 /* Store the arg pointer in the __va_stk member. */
2595 emit_move_insn (change_address (block, Pmode,
2596 plus_constant (XEXP (block, 0),
2598 copy_to_reg (virtual_incoming_args_rtx));
2600 /* Allocate the register space, and store it as the __va_reg member. */
2601 addr = assign_stack_local (BLKmode, 8 * UNITS_PER_WORD, -1);
2602 MEM_IN_STRUCT_P (addr) = 1;
2603 RTX_UNCHANGING_P (addr) = 1;
2604 RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
2605 emit_move_insn (change_address (block, Pmode,
2606 plus_constant (XEXP (block, 0),
2607 2 * UNITS_PER_WORD)),
2608 copy_to_reg (XEXP (addr, 0)));
2610 /* Now store the incoming registers. */
2614 change_address (addr, Pmode,
2615 plus_constant (XEXP (addr, 0),
2616 fixed * UNITS_PER_WORD)),
2619 /* Return the address of the va_list constructor, but don't put it in a
2620 register. This fails when not optimizing and produces worse code when
2622 return XEXP (block, 0);
2625 /* If cmpsi has not been generated, emit code to do the test. Return the
2626 expression describing the test of operator OP. */
2629 emit_test (op, mode)
2631 enum machine_mode mode;
2633 if (m88k_compare_reg == 0)
2634 emit_insn (gen_test (m88k_compare_op0, m88k_compare_op1));
2635 return (gen_rtx (op, mode, m88k_compare_reg, const0_rtx));
2638 /* Determine how to best perform cmpsi/bxx, where cmpsi has a constant
2639 operand. All tests with zero (albeit swapped) and all equality tests
2640 with a constant are done with bcnd. The remaining cases are swapped
2644 emit_bcnd (op, label)
2648 if (m88k_compare_op1 == const0_rtx)
2649 emit_jump_insn (optimize
2650 ? gen_bxx (emit_test (op, VOIDmode), label)
2651 : gen_bcnd (gen_rtx (op, VOIDmode,
2652 m88k_compare_op0, const0_rtx),
2654 else if (m88k_compare_op0 == const0_rtx)
2655 emit_jump_insn (optimize
2656 ? gen_bxx (emit_test (op, VOIDmode), label)
2657 : gen_bcnd (gen_rtx (swap_condition (op), VOIDmode,
2658 m88k_compare_op1, const0_rtx),
2660 else if (op != EQ && op != NE)
2661 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2664 rtx zero = gen_reg_rtx (SImode);
2668 if (GET_CODE (m88k_compare_op1) == CONST_INT)
2670 reg = force_reg (SImode, m88k_compare_op0);
2671 constant = m88k_compare_op1;
2675 reg = force_reg (SImode, m88k_compare_op1);
2676 constant = m88k_compare_op0;
2678 value = INTVAL (constant);
2680 /* Perform an arithmetic computation to make the compared-to value
2681 zero, but avoid loosing if the bcnd is later changed into sxx. */
2682 if (SMALL_INTVAL (value))
2683 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2686 if (SMALL_INTVAL (-value))
2687 emit_insn (gen_addsi3 (zero, reg,
2688 gen_rtx (CONST_INT, VOIDmode, -value)));
2690 emit_insn (gen_xorsi3 (zero, reg, constant));
2692 emit_jump_insn (gen_bcnd (gen_rtx (op, VOIDmode,
2699 /* Print an operand. Recognize special options, documented below. */
2702 print_operand (file, x, code)
2707 enum rtx_code xc = (x ? GET_CODE (x) : UNKNOWN);
2708 register int value = (xc == CONST_INT ? INTVAL (x) : 0);
2709 static int sequencep;
2710 static int reversep;
2714 if (code < 'B' || code > 'E')
2715 output_operand_lossage ("%R not followed by %B/C/D/E");
2717 xc = reverse_condition (xc);
2723 case '*': /* addressing base register for PIC */
2724 fputs (reg_names[PIC_OFFSET_TABLE_REGNUM], file); return;
2726 case '#': /* SVR4 pound-sign syntax character (empty if SVR3) */
2727 fputs (m88k_pound_sign, file); return;
2729 case 'X': /* print the upper 16 bits... */
2731 case 'x': /* print the lower 16 bits of the integer constant in hex */
2732 if (xc != CONST_INT)
2733 output_operand_lossage ("invalid %x/X value");
2734 fprintf (file, "0x%x", value & 0xffff); return;
2736 case 'H': /* print the low 16 bits of the negated integer constant */
2737 if (xc != CONST_INT)
2738 output_operand_lossage ("invalid %H value");
2740 case 'h': /* print the register or low 16 bits of the integer constant */
2743 if (xc != CONST_INT)
2744 output_operand_lossage ("invalid %h value");
2745 fprintf (file, "%d", value & 0xffff);
2748 case 'Q': /* print the low 8 bits of the negated integer constant */
2749 if (xc != CONST_INT)
2750 output_operand_lossage ("invalid %Q value");
2752 case 'q': /* print the register or low 8 bits of the integer constant */
2755 if (xc != CONST_INT)
2756 output_operand_lossage ("invalid %q value");
2757 fprintf (file, "%d", value & 0xff);
2760 case 'w': /* print the integer constant (X == 32 ? 0 : 32 - X) */
2761 if (xc != CONST_INT)
2762 output_operand_lossage ("invalid %o value");
2763 fprintf (file, "%d", value == 32 ? 0 : 32 - value);
2766 case 'p': /* print the logarithm of the integer constant */
2768 || (value = exact_log2 (value)) < 0)
2769 output_operand_lossage ("invalid %p value");
2770 fprintf (file, "%d", value);
2773 case 'S': /* compliment the value and then... */
2775 case 's': /* print the width and offset values forming the integer
2776 constant with a SET instruction. See integer_ok_for_set. */
2778 register unsigned mask, uval = value;
2779 register int top, bottom;
2781 if (xc != CONST_INT)
2782 output_operand_lossage ("invalid %s/S value");
2783 /* All the "one" bits must be contiguous. If so, MASK will be
2784 a power of two or zero. */
2785 mask = (uval | (uval - 1)) + 1;
2786 if (!(uval && POWER_OF_2_or_0 (mask)))
2787 output_operand_lossage ("invalid %s/S value");
2788 top = mask ? exact_log2 (mask) : 32;
2789 bottom = exact_log2 (uval & ~(uval - 1));
2790 fprintf (file,"%d<%d>", top - bottom, bottom);
2794 case 'P': /* print nothing if pc_rtx; output label_ref */
2795 if (xc == LABEL_REF)
2796 output_addr_const (file, x);
2798 output_operand_lossage ("invalid %P operand");
2801 case 'L': /* print 0 or 1 if operand is label_ref and then... */
2802 fputc (xc == LABEL_REF ? '1' : '0', file);
2803 case '.': /* print .n if delay slot is used */
2804 fputs ((final_sequence
2805 && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
2806 ? ".n\t" : "\t", file);
2809 case 'R': /* reverse the condition of the next print_operand
2810 if operand is a label_ref. */
2812 reversep = (xc == LABEL_REF);
2815 case 'B': /* bcnd branch values */
2816 fputs (m88k_pound_sign, file);
2819 case EQ: fputs ("eq0", file); return;
2820 case NE: fputs ("ne0", file); return;
2821 case GT: fputs ("gt0", file); return;
2822 case LE: fputs ("le0", file); return;
2823 case LT: fputs ("lt0", file); return;
2824 case GE: fputs ("ge0", file); return;
2825 default: output_operand_lossage ("invalid %B value");
2828 case 'C': /* bb0/bb1 branch values for comparisons */
2829 fputs (m88k_pound_sign, file);
2832 case EQ: fputs ("eq", file); return;
2833 case NE: fputs ("ne", file); return;
2834 case GT: fputs ("gt", file); return;
2835 case LE: fputs ("le", file); return;
2836 case LT: fputs ("lt", file); return;
2837 case GE: fputs ("ge", file); return;
2838 case GTU: fputs ("hi", file); return;
2839 case LEU: fputs ("ls", file); return;
2840 case LTU: fputs ("lo", file); return;
2841 case GEU: fputs ("hs", file); return;
2842 default: output_operand_lossage ("invalid %C value");
2845 case 'D': /* bcnd branch values for float comparisons */
2848 case EQ: fputs ("0xa", file); return;
2849 case NE: fputs ("0x5", file); return;
2850 case GT: fputs (m88k_pound_sign, file);
2851 fputs ("gt0", file); return;
2852 case LE: fputs ("0xe", file); return;
2853 case LT: fputs ("0x4", file); return;
2854 case GE: fputs ("0xb", file); return;
2855 default: output_operand_lossage ("invalid %D value");
2858 case 'E': /* bcnd branch values for special integers */
2861 case EQ: fputs ("0x8", file); return;
2862 case NE: fputs ("0x7", file); return;
2863 default: output_operand_lossage ("invalid %E value");
2866 case 'd': /* second register of a two register pair */
2868 output_operand_lossage ("`%d' operand isn't a register");
2869 fputs (reg_names[REGNO (x) + 1], file);
2872 case 'r': /* an immediate 0 should be represented as `r0' */
2873 if (x == const0_rtx)
2875 fputs (reg_names[0], file);
2879 output_operand_lossage ("invalid %r value");
2885 if (REGNO (x) == ARG_POINTER_REGNUM)
2886 output_operand_lossage ("operand is r0");
2888 fputs (reg_names[REGNO (x)], file);
2890 else if (xc == PLUS)
2893 output_address (XEXP (x, 0));
2894 else if (xc == CONST_DOUBLE)
2895 output_operand_lossage ("operand is const_double");
2897 output_addr_const (file, x);
2900 case 'g': /* append #got_rel as needed */
2901 if (flag_pic && (xc == SYMBOL_REF || xc == LABEL_REF))
2903 output_addr_const (file, x);
2904 fputs ("#got_rel", file);
2909 case 'a': /* (standard), assume operand is an address */
2910 case 'c': /* (standard), assume operand is an immediate value */
2911 case 'l': /* (standard), assume operand is a label_ref */
2912 case 'n': /* (standard), like %c, except negate first */
2914 output_operand_lossage ("invalid code");
2919 print_operand_address (file, addr)
2923 register rtx reg0, reg1, temp;
2925 switch (GET_CODE (addr))
2928 if (REGNO (addr) == ARG_POINTER_REGNUM)
2931 fprintf (file, "%s,%s", reg_names[0], reg_names [REGNO (addr)]);
2935 fprintf (file, "%s,%slo16(",
2936 reg_names[REGNO (XEXP (addr, 0))], m88k_pound_sign);
2937 output_addr_const (file, XEXP (addr, 1));
2942 reg0 = XEXP (addr, 0);
2943 reg1 = XEXP (addr, 1);
2944 if (GET_CODE (reg0) == MULT || GET_CODE (reg0) == CONST_INT)
2951 if ((REG_P (reg0) && REGNO (reg0) == ARG_POINTER_REGNUM)
2952 || (REG_P (reg1) && REGNO (reg1) == ARG_POINTER_REGNUM))
2955 else if (REG_P (reg0))
2958 fprintf (file, "%s,%s",
2959 reg_names [REGNO (reg0)], reg_names [REGNO (reg1)]);
2961 else if (GET_CODE (reg1) == CONST_INT)
2962 fprintf (file, "%s,%d",
2963 reg_names [REGNO (reg0)], INTVAL (reg1));
2965 else if (GET_CODE (reg1) == MULT)
2967 rtx mreg = XEXP (reg1, 0);
2968 if (REGNO (mreg) == ARG_POINTER_REGNUM)
2971 fprintf (file, "%s[%s]", reg_names[REGNO (reg0)],
2972 reg_names[REGNO (mreg)]);
2975 else if (GET_CODE (reg1) == ZERO_EXTRACT)
2977 fprintf (file, "%s,%slo16(",
2978 reg_names[REGNO (reg0)], m88k_pound_sign);
2979 output_addr_const (file, XEXP (reg1, 0));
2985 fprintf (file, "%s,", reg_names[REGNO (reg0)]);
2986 output_addr_const (file, reg1);
2987 fputs ("#got_rel", file);
2997 if (REGNO (XEXP (addr, 0)) == ARG_POINTER_REGNUM)
3000 fprintf (file, "%s[%s]",
3001 reg_names[0], reg_names[REGNO (XEXP (addr, 0))]);
3005 fprintf (file, "%s,%shi16(", reg_names[0], m88k_pound_sign);
3006 output_addr_const (file, XEXP (addr, 0));
3011 fprintf (file, "%s,%d", reg_names[0], INTVAL (addr));
3015 fprintf (file, "%s,", reg_names[0]);
3016 if (SHORT_ADDRESS_P (addr, temp))
3018 fprintf (file, "%siw16(", m88k_pound_sign);
3019 output_addr_const (file, addr);
3023 output_addr_const (file, addr);