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.2.3.6 29 Jun 1992 16:06:14";
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 /* Generate the assembly code for function entry.
1458 The prologue is responsible for setting up the stack frame,
1459 initializing the frame pointer register, saving registers that must be
1460 saved, and allocating SIZE additional bytes of storage for the
1461 local variables. SIZE is an integer. FILE is a stdio
1462 stream to which the assembler code should be output.
1464 The label for the beginning of the function need not be output by this
1465 macro. That has already been done when the macro is run.
1467 To determine which registers to save, the macro can refer to the array
1468 `regs_ever_live': element R is nonzero if hard register
1469 R is used anywhere within the function. This implies the
1470 function prologue should save register R, but not if it is one
1471 of the call-used registers.
1473 On machines where functions may or may not have frame-pointers, the
1474 function entry code must vary accordingly; it must set up the frame
1475 pointer if one is wanted, and not otherwise. To determine whether a
1476 frame pointer is in wanted, the macro can refer to the variable
1477 `frame_pointer_needed'. The variable's value will be 1 at run
1478 time in a function that needs a frame pointer.
1480 On machines where an argument may be passed partly in registers and
1481 partly in memory, this macro must examine the variable
1482 `current_function_pretend_args_size', and allocate that many bytes
1483 of uninitialized space on the stack just underneath the first argument
1484 arriving on the stack. (This may not be at the very end of the stack,
1485 if the calling sequence has pushed anything else since pushing the stack
1486 arguments. But usually, on such machines, nothing else has been pushed
1487 yet, because the function prologue itself does all the pushing.)
1489 If `ACCUMULATE_OUTGOING_ARGS' is defined, the variable
1490 `current_function_outgoing_args_size' contains the size in bytes
1491 required for the outgoing arguments. This macro must add that
1492 amount of uninitialized space to very bottom of the stack.
1494 The stack frame we use looks like this:
1497 |==============================================|
1499 |==============================================|
1500 | [caller's outgoing memory arguments] |
1501 |==============================================|
1502 | caller's outgoing argument area (32 bytes) |
1503 sp -> |==============================================| <- ap
1504 | [local variable space] |
1505 |----------------------------------------------|
1506 | [return address (r1)] |
1507 |----------------------------------------------|
1508 | [previous frame pointer (r30)] |
1509 |==============================================| <- fp
1510 | [preserved registers (r25..r14)] |
1511 |----------------------------------------------|
1512 | [preserved registers (x29..x22)] |
1513 |==============================================|
1514 | [dynamically allocated space (alloca)] |
1515 |==============================================|
1516 | [callee's outgoing memory arguments] |
1517 |==============================================|
1518 | [callee's outgoing argument area (32 bytes)] |
1519 |==============================================| <- sp
1523 r1 and r30 must be saved if debugging.
1525 fp (if present) is located two words down from the local
1529 static void emit_add ();
1530 static void preserve_registers ();
1531 static void emit_ldst ();
1532 static void output_tdesc ();
1536 static char save_regs[FIRST_PSEUDO_REGISTER];
1537 static int frame_laid_out;
1538 static int frame_size;
1539 static int variable_args_p;
1540 static int epilogue_marked;
1542 extern char call_used_regs[];
1543 extern int current_function_pretend_args_size;
1544 extern int current_function_outgoing_args_size;
1545 extern int frame_pointer_needed;
1547 #define FIRST_OCS_PRESERVE_REGISTER 14
1548 #define LAST_OCS_PRESERVE_REGISTER 30
1550 #define FIRST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 22)
1551 #define LAST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 31)
1553 #define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
1554 #define ROUND_CALL_BLOCK_SIZE(BYTES) \
1555 (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
1557 /* Establish the position of the FP relative to the SP. This is done
1558 either during FUNCTION_PROLOGUE or by INITIAL_ELIMINATION_OFFSET. */
1561 m88k_layout_frame ()
1567 bzero ((char *) &save_regs[0], sizeof (save_regs));
1568 sp_size = nregs = nxregs = 0;
1569 frame_size = get_frame_size ();
1571 /* Since profiling requires a call, make sure r1 is saved. */
1572 if (profile_flag || profile_block_flag)
1575 /* If we are producing debug information, store r1 and r30 where the
1576 debugger wants to find them (r30 at r30+0, r1 at r30+4). Space has
1577 already been reserved for r1/r30 in STARTING_FRAME_OFFSET. */
1578 if (write_symbols != NO_DEBUG && !TARGET_OCS_FRAME_POSITION)
1581 /* If there is a call, alloca is used, __builtin_alloca is used, or
1582 a dynamic-sized object is defined, add the 8 additional words
1583 for the callee's argument area. The common denominator is that the
1584 FP is required. may_call_alloca only gets calls to alloca;
1585 current_function_calls_alloca gets alloca and __builtin_alloca. */
1586 if (regs_ever_live[1] || frame_pointer_needed)
1589 sp_size += REG_PARM_STACK_SPACE (0);
1592 /* If we are producing PIC, save the addressing base register and r1. */
1593 if (flag_pic && current_function_uses_pic_offset_table)
1595 save_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
1599 /* If a frame is requested, save the previous FP, and the return
1600 address (r1), so that a traceback can be done without using tdesc
1601 information. Otherwise, simply save the FP if it is used as
1602 a preserve register. */
1603 if (frame_pointer_needed)
1604 save_regs[FRAME_POINTER_REGNUM] = save_regs[1] = 1;
1605 else if (regs_ever_live[FRAME_POINTER_REGNUM])
1606 save_regs[FRAME_POINTER_REGNUM] = 1;
1608 /* Figure out which extended register(s) needs to be saved. */
1609 for (regno = FIRST_EXTENDED_REGISTER + 1; regno < FIRST_PSEUDO_REGISTER;
1611 if (regs_ever_live[regno] && ! call_used_regs[regno])
1613 save_regs[regno] = 1;
1617 /* Figure out which normal register(s) needs to be saved. */
1618 for (regno = 2; regno < FRAME_POINTER_REGNUM; regno++)
1619 if (regs_ever_live[regno] && ! call_used_regs[regno])
1621 save_regs[regno] = 1;
1625 /* Achieve greatest use of double memory ops. Either we end up saving
1626 r30 or we use that slot to align the registers we do save. */
1627 if (nregs >= 2 && save_regs[1] && !save_regs[FRAME_POINTER_REGNUM])
1630 nregs += save_regs[1] + save_regs[FRAME_POINTER_REGNUM];
1631 /* if we need to align extended registers, add a word */
1632 if (nxregs > 0 && (nregs & 1) != 0)
1634 sp_size += 4 * nregs;
1635 sp_size += 8 * nxregs;
1636 sp_size += current_function_outgoing_args_size;
1638 /* The first two saved registers are placed above the new frame pointer
1639 if any. In the only case this matters, they are r1 and r30. */
1640 if (frame_pointer_needed || sp_size)
1641 m88k_fp_offset = ROUND_CALL_BLOCK_SIZE (sp_size - STARTING_FRAME_OFFSET);
1643 m88k_fp_offset = -STARTING_FRAME_OFFSET;
1644 m88k_stack_size = m88k_fp_offset + STARTING_FRAME_OFFSET;
1646 /* First, combine m88k_stack_size and size. If m88k_stack_size is
1647 non-zero, align the frame size to 8 mod 16; otherwise align the
1648 frame size to 0 mod 16. (If stacks are 8 byte aligned, this ends
1652 = ((m88k_stack_size ? STACK_UNIT_BOUNDARY - STARTING_FRAME_OFFSET : 0)
1653 - (frame_size % STACK_UNIT_BOUNDARY));
1657 need += STACK_UNIT_BOUNDARY;
1658 (void) assign_stack_local (BLKmode, need, BITS_PER_UNIT);
1659 frame_size = get_frame_size ();
1662 = ROUND_CALL_BLOCK_SIZE (m88k_stack_size + frame_size
1663 + current_function_pretend_args_size);
1667 /* Return true if this function is known to have a null epilogue. */
1672 if (! reload_completed)
1674 if (! frame_laid_out)
1675 m88k_layout_frame ();
1676 return (! frame_pointer_needed
1679 && m88k_stack_size == 0);
1682 /* Determine if the current function has any references to the arg pointer.
1683 This is done indirectly by examining the DECL_ARGUMENTS' DECL_RTL.
1684 It is OK to return TRUE if there are no references, but FALSE must be
1692 if (current_function_decl == 0
1693 || current_function_varargs
1697 for (parm = DECL_ARGUMENTS (current_function_decl);
1699 parm = TREE_CHAIN (parm))
1701 if (DECL_RTL (parm) == 0
1702 || GET_CODE (DECL_RTL (parm)) == MEM)
1705 if (DECL_INCOMING_RTL (parm) == 0
1706 || GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
1713 m88k_begin_prologue (stream, size)
1717 epilogue_marked = 0;
1718 m88k_prologue_done = 1; /* it's ok now to put out ln directives */
1722 m88k_end_prologue (stream)
1725 if (TARGET_OCS_DEBUG_INFO)
1726 PUT_OCS_FUNCTION_START (stream);
1727 if (epilogue_marked)
1732 m88k_expand_prologue ()
1734 int old_fp_offset = m88k_fp_offset;
1735 int old_stack_size = m88k_stack_size;
1737 m88k_layout_frame ();
1738 #if (MONITOR_GCC & 0x8) /* Watch for suspicious register elimination changes. */
1739 if (frame_laid_out > 1)
1741 if (old_fp_offset != m88k_fp_offset)
1742 warning ("Internal gcc error: FP offset has changed by %d bytes",
1743 m88k_fp_offset - old_fp_offset);
1744 if (old_stack_size != m88k_stack_size)
1745 warning ("Internal gcc error: stack size has changed by %d bytes",
1746 m88k_stack_size - old_stack_size);
1751 if (TARGET_OPTIMIZE_ARG_AREA
1753 && ! uses_arg_area_p ())
1755 /* The incoming argument area is used for stack space if it is not
1756 used (or if -mno-use-arg-area is given). */
1757 if ((m88k_stack_size -= REG_PARM_STACK_SPACE (0)) < 0)
1758 m88k_stack_size = 0;
1761 if (m88k_stack_size)
1762 emit_add (stack_pointer_rtx, stack_pointer_rtx, -m88k_stack_size);
1764 if (nregs || nxregs)
1765 preserve_registers (m88k_fp_offset + 4, 1);
1767 if (frame_pointer_needed)
1768 emit_add (frame_pointer_rtx, stack_pointer_rtx, m88k_fp_offset);
1770 if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM])
1772 rtx return_reg = gen_rtx (REG, SImode, 1);
1773 rtx label = gen_label_rtx ();
1778 temp_reg = gen_rtx (REG, SImode, TEMP_REGNUM);
1779 emit_move_insn (temp_reg, return_reg);
1781 emit_insn (gen_locate1 (pic_offset_table_rtx, label));
1782 emit_insn (gen_locate2 (pic_offset_table_rtx, label));
1783 emit_insn (gen_addsi3 (pic_offset_table_rtx,
1784 pic_offset_table_rtx, return_reg));
1786 emit_move_insn (return_reg, temp_reg);
1788 if (profile_flag || profile_block_flag)
1789 emit_insn (gen_profiler ());
1792 /* This function generates the assembly code for function exit,
1793 on machines that need it. Args are same as for FUNCTION_PROLOGUE.
1795 The function epilogue should not depend on the current stack pointer!
1796 It should use the frame pointer only, if there is a frame pointer.
1797 This is mandatory because of alloca; we also take advantage of it to
1798 omit stack adjustments before returning. */
1801 m88k_begin_epilogue (stream)
1804 if (TARGET_OCS_DEBUG_INFO)
1805 PUT_OCS_FUNCTION_END (stream);
1806 epilogue_marked = 1;
1810 m88k_end_epilogue (stream, size)
1814 if (TARGET_OCS_DEBUG_INFO && !epilogue_marked)
1815 PUT_OCS_FUNCTION_END (stream);
1817 output_short_branch_defs (stream);
1819 fprintf (stream, "\n");
1821 if (TARGET_OCS_DEBUG_INFO)
1822 output_tdesc (stream, m88k_fp_offset + 4);
1824 m88k_function_number++;
1825 m88k_prologue_done = 0; /* don't put out ln directives */
1826 variable_args_p = 0; /* has variable args */
1830 m88k_expand_epilogue ()
1832 #if (MONITOR_GCC & 0x4) /* What are interesting prologue/epilogue values? */
1833 fprintf (stream, "; size = %d, m88k_fp_offset = %d, m88k_stack_size = %d\n",
1834 size, m88k_fp_offset, m88k_stack_size);
1837 if (frame_pointer_needed)
1838 emit_add (stack_pointer_rtx, frame_pointer_rtx, -m88k_fp_offset);
1840 if (nregs || nxregs)
1841 preserve_registers (m88k_fp_offset + 4, 0);
1843 if (m88k_stack_size)
1844 emit_add (stack_pointer_rtx, stack_pointer_rtx, m88k_stack_size);
1847 /* Emit insns to set DSTREG to SRCREG + AMOUNT during the prologue or
1851 emit_add (dstreg, srcreg, amount)
1856 rtx incr = gen_rtx (CONST_INT, VOIDmode, abs (amount));
1857 if (! ADD_INTVAL (amount))
1859 rtx temp = gen_rtx (REG, SImode, TEMP_REGNUM);
1860 emit_move_insn (temp, incr);
1863 emit_insn ((amount < 0 ? gen_subsi3 : gen_addsi3) (dstreg, srcreg, incr));
1866 /* Save/restore the preserve registers. base is the highest offset from
1867 r31 at which a register is stored. store_p is true if stores are to
1868 be done; otherwise loads. */
1871 preserve_registers (base, store_p)
1880 } mem_op[FIRST_PSEUDO_REGISTER];
1881 struct mem_op *mo_ptr = mem_op;
1883 /* The 88open OCS mandates that preserved registers be stored in
1884 increasing order. For compatibility with current practice,
1885 the order is r1, r30, then the preserve registers. */
1890 /* An extra word is given in this case to make best use of double
1892 if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM])
1894 emit_ldst (store_p, 1, SImode, offset);
1899 /* Walk the registers to save recording all single memory operations. */
1900 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
1901 if (save_regs[regno])
1903 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
1906 mo_ptr->regno = regno;
1907 mo_ptr->offset = offset;
1918 /* Walk the registers to save recording all double memory operations.
1919 This avoids a delay in the epilogue (ld.d/ld). */
1921 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
1922 if (save_regs[regno])
1924 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
1931 mo_ptr->regno = regno-1;
1932 mo_ptr->offset = offset-4;
1939 /* Walk the extended registers to record all memory operations. */
1940 /* Be sure the offset is double word aligned. */
1941 offset = (offset - 1) & ~7;
1942 for (regno = FIRST_PSEUDO_REGISTER - 1; regno > FIRST_EXTENDED_REGISTER;
1944 if (save_regs[regno])
1947 mo_ptr->regno = regno;
1948 mo_ptr->offset = offset;
1955 /* Output the memory operations. */
1956 for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++)
1959 emit_ldst (store_p, mo_ptr->regno,
1960 (mo_ptr->nregs > 1 ? DImode : SImode),
1966 emit_ldst (store_p, regno, mode, offset)
1969 enum machine_mode mode;
1972 rtx reg = gen_rtx (REG, mode, regno);
1973 rtx mem = gen_rtx (MEM, mode, plus_constant (stack_pointer_rtx, offset));
1976 emit_move_insn (mem, reg);
1978 emit_move_insn (reg, mem);
1981 /* Convert the address expression REG to a CFA offset. */
1984 m88k_debugger_offset (reg, offset)
1986 register int offset;
1988 if (GET_CODE (reg) == PLUS)
1990 offset = INTVAL (XEXP (reg, 1));
1991 reg = XEXP (reg, 0);
1994 /* Put the offset in terms of the CFA (arg pointer). */
1995 if (reg == frame_pointer_rtx)
1996 offset += m88k_fp_offset - m88k_stack_size;
1997 else if (reg == stack_pointer_rtx)
1998 offset -= m88k_stack_size;
1999 else if (reg != arg_pointer_rtx)
2001 #if (MONITOR_GCC & 0x10) /* Watch for suspicious symbolic locations. */
2002 if (! (GET_CODE (reg) == REG
2003 && REGNO (reg) >= FIRST_PSEUDO_REGISTER))
2004 warning ("Internal gcc error: Can't express symbolic location");
2012 /* Output the 88open OCS proscribed text description information.
2015 0 22: info-byte-length (16 or 20 bytes)
2016 0 2: info-alignment (word 2)
2017 1 32: info-protocol (version 1 or 2(pic))
2018 2 32: starting-address (inclusive, not counting prologue)
2019 3 32: ending-address (exclusive, not counting epilog)
2020 4 8: info-variant (version 1 or 3(extended registers))
2021 4 17: register-save-mask (from register 14 to 30)
2023 4 1: return-address-info-discriminant
2024 4 5: frame-address-register
2025 5 32: frame-address-offset
2026 6 32: return-address-info
2027 7 32: register-save-offset
2028 8 16: extended-register-save-mask (x16 - x31)
2029 8 16: extended-register-save-offset (WORDS from register-save-offset) */
2032 output_tdesc (file, offset)
2037 long mask, return_address_info, register_save_offset;
2038 long xmask, xregister_save_offset;
2041 for (mask = 0, i = 0, regno = FIRST_OCS_PRESERVE_REGISTER;
2042 regno <= LAST_OCS_PRESERVE_REGISTER;
2046 if (save_regs[regno])
2053 for (xmask = 0, j = 0, regno = FIRST_OCS_EXTENDED_PRESERVE_REGISTER;
2054 regno <= LAST_OCS_EXTENDED_PRESERVE_REGISTER;
2058 if (save_regs[regno])
2067 if ((nxregs > 0 || nregs > 2) && !save_regs[FRAME_POINTER_REGNUM])
2069 return_address_info = - m88k_stack_size + offset;
2070 register_save_offset = return_address_info - i*4;
2074 return_address_info = 1;
2075 register_save_offset = - m88k_stack_size + offset + 4 - i*4;
2078 xregister_save_offset = - (j * 2 + ((register_save_offset >> 2) & 1));
2082 fprintf (file, "\t%s\t %d,%d", INT_ASM_OP, /* 8:0,22:(20 or 16),2:2 */
2083 (((xmask != 0) ? 20 : 16) << 2) | 2,
2086 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_START_PREFIX, m88k_function_number);
2087 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2088 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_END_PREFIX, m88k_function_number);
2089 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2091 fprintf (file, ",0x%x,0x%x,0x%x,0x%x",
2092 /* 8:1,17:0x%.3x,1:0,1:%d,5:%d */
2093 (((xmask ? 3 : 1) << (17+1+1+5))
2095 | ((!!save_regs[1]) << 5)
2096 | (frame_pointer_needed
2097 ? FRAME_POINTER_REGNUM
2098 : STACK_POINTER_REGNUM)),
2099 (m88k_stack_size - (frame_pointer_needed ? m88k_fp_offset : 0)),
2100 return_address_info,
2101 register_save_offset);
2103 fprintf (file, ",0x%x%04x", xmask, (0xffff & xregister_save_offset));
2109 /* Output assembler code to FILE to increment profiler label # LABELNO
2110 for profiling a function entry. NAME is the mcount function name
2111 (varies), SAVEP indicates whether the parameter registers need to
2112 be saved and restored. */
2115 output_function_profiler (file, labelno, name, savep)
2123 char *temp = (savep ? reg_names[2] : reg_names[10]);
2127 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2128 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2129 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2130 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2131 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2134 ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno);
2137 fprintf (file, "\tor.u\t %s,%s,%shi16(%s#got_rel)\n",
2138 temp, reg_names[0], m88k_pound_sign, &label[1]);
2139 fprintf (file, "\tor\t %s,%s,%slo16(%s#got_rel)\n",
2140 temp, temp, m88k_pound_sign, &label[1]);
2141 sprintf (dbi, "\tld\t %s,%s,%s\n", temp,
2142 reg_names[PIC_OFFSET_TABLE_REGNUM], temp);
2146 sprintf (dbi, "\tld\t %s,%s,%s#got_rel\n", temp,
2147 reg_names[PIC_OFFSET_TABLE_REGNUM], &label[1]);
2151 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n",
2152 temp, reg_names[0], m88k_pound_sign, &label[1]);
2153 sprintf (dbi, "\tor\t %s,%s,%slo16(%s)\n",
2154 temp, temp, m88k_pound_sign, &label[1]);
2158 fprintf (file, "\tbsr.n\t %s#plt\n", name);
2160 fprintf (file, "\tbsr.n\t %s\n", name);
2165 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2166 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2167 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2168 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2169 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2173 /* Output assembler code to FILE to initialize basic-block profiling for
2174 the current module. LABELNO is unique to each instance. */
2177 output_function_block_profiler (file, labelno)
2184 ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 0);
2185 ASM_GENERATE_INTERNAL_LABEL (label, "LPY", labelno);
2187 /* @@ Need to deal with PIC. I'm not sure what the requirements are on
2188 register usage, so I used r26/r27 to be safe. */
2189 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n", reg_names[27], reg_names[0],
2190 m88k_pound_sign, &block[1]);
2191 fprintf (file, "\tld\t %s,%s,%slo16(%s)\n", reg_names[26], reg_names[27],
2192 m88k_pound_sign, &block[1]);
2193 fprintf (file, "\tbcnd\t %sne0,%s,%s\n",
2194 m88k_pound_sign, reg_names[26], &label[1]);
2195 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2196 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2197 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2198 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2199 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2200 fputs ("\tbsr.n\t ", file);
2201 ASM_OUTPUT_LABELREF (file, "__bb_init_func");
2203 fprintf (file, "\tor\t %s,%s,%slo16(%s)\n", reg_names[2], reg_names[27],
2204 m88k_pound_sign, &block[1]);
2205 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2206 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2207 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2208 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2209 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2210 ASM_OUTPUT_INTERNAL_LABEL (file, "LPY", labelno);
2213 /* Output assembler code to FILE to increment the count associated with
2214 the basic block number BLOCKNO. */
2217 output_block_profiler (file, blockno)
2223 ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 2);
2225 /* @@ Need to deal with PIC. I'm not sure what the requirements are on
2226 register usage, so I used r26/r27 to be safe. */
2227 fprintf (file, "\tor.u\t %s,%s,%shi16(%s+%d)\n", reg_names[27], reg_names[0],
2228 m88k_pound_sign, &block[1], 4 * blockno);
2229 fprintf (file, "\tld\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27],
2230 m88k_pound_sign, &block[1], 4 * blockno);
2231 fprintf (file, "\taddu\t %s,%s,1\n", reg_names[26], reg_names[26]);
2232 fprintf (file, "\tst\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27],
2233 m88k_pound_sign, &block[1], 4 * blockno);
2236 /* Determine whether a function argument is passed in a register, and
2239 The arguments are CUM, which summarizes all the previous
2240 arguments; MODE, the machine mode of the argument; TYPE,
2241 the data type of the argument as a tree node or 0 if that is not known
2242 (which happens for C support library functions); and NAMED,
2243 which is 1 for an ordinary argument and 0 for nameless arguments that
2244 correspond to `...' in the called function's prototype.
2246 The value of the expression should either be a `reg' RTX for the
2247 hard register in which to pass the argument, or zero to pass the
2248 argument on the stack.
2250 On the m88000 the first eight words of args are normally in registers
2251 and the rest are pushed. Double precision floating point must be
2252 double word aligned (and if in a register, starting on an even
2253 register). Structures and unions which are not 4 byte, and word
2254 aligned are passed in memory rather than registers, even if they
2255 would fit completely in the registers under OCS rules.
2257 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2258 For structures that are passed in memory, but could have been
2259 passed in registers, we first load the structure into the
2260 register, and then when the last argument is passed, we store
2261 the registers into the stack locations. This fixes some bugs
2262 where GCC did not expect to have register arguments, followed
2263 by stack arguments, followed by register arguments. */
2266 m88k_function_arg (args_so_far, mode, type, named)
2267 CUMULATIVE_ARGS args_so_far;
2268 enum machine_mode mode;
2274 if (type != 0 /* undo putting struct in register */
2275 && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
2278 if (mode == BLKmode && TARGET_WARN_PASS_STRUCT)
2279 warning ("argument #%d is a structure", args_so_far + 1);
2281 if ((args_so_far & 1) != 0
2282 && (mode == DImode || mode == DFmode
2283 || (type != 0 && TYPE_ALIGN (type) > 32)))
2288 return (rtx) 0; /* don't put args in registers */
2291 if (type == 0 && mode == BLKmode)
2292 abort (); /* m88k_function_arg argument `type' is NULL for BLKmode. */
2294 bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
2295 words = (bytes + 3) / 4;
2297 if (args_so_far + words > 8)
2298 return (rtx) 0; /* args have exhausted registers */
2300 else if (mode == BLKmode
2301 && (TYPE_ALIGN (type) != BITS_PER_WORD
2302 || bytes != UNITS_PER_WORD))
2305 return gen_rtx (REG,
2306 ((mode == BLKmode) ? TYPE_MODE (type) : mode),
2310 /* Do what is necessary for `va_start'. The argument is ignored;
2311 We look at the current function to determine if stdargs or varargs
2312 is used and fill in an initial va_list. A pointer to this constructor
2316 m88k_builtin_saveregs (arglist)
2319 rtx block, addr, argsize;
2320 tree fntype = TREE_TYPE (current_function_decl);
2321 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2322 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2323 != void_type_node)))
2324 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
2326 variable_args_p = 1;
2328 if (CONSTANT_P (current_function_arg_offset_rtx))
2330 fixed = (XINT (current_function_arg_offset_rtx, 0)
2331 + argadj) / UNITS_PER_WORD;
2332 argsize = gen_rtx (CONST_INT, VOIDmode, fixed);
2337 argsize = plus_constant (current_function_arg_offset_rtx, argadj);
2338 argsize = expand_shift (RSHIFT_EXPR, Pmode, argsize,
2339 build_int_2 (2, 0), argsize, 0);
2342 /* Allocate the va_list constructor */
2343 block = assign_stack_local (BLKmode, 3 * UNITS_PER_WORD, BITS_PER_WORD);
2344 RTX_UNCHANGING_P (block) = 1;
2345 RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
2347 /* Store the argsize as the __va_arg member. */
2348 emit_move_insn (change_address (block, SImode, XEXP (block, 0)),
2351 /* Store the arg pointer in the __va_stk member. */
2352 emit_move_insn (change_address (block, Pmode,
2353 plus_constant (XEXP (block, 0),
2355 copy_to_reg (virtual_incoming_args_rtx));
2357 /* Allocate the register space, and store it as the __va_reg member. */
2358 addr = assign_stack_local (BLKmode, 8 * UNITS_PER_WORD, -1);
2359 MEM_IN_STRUCT_P (addr) = 1;
2360 RTX_UNCHANGING_P (addr) = 1;
2361 RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
2362 emit_move_insn (change_address (block, Pmode,
2363 plus_constant (XEXP (block, 0),
2364 2 * UNITS_PER_WORD)),
2365 copy_to_reg (XEXP (addr, 0)));
2367 /* Now store the incoming registers. */
2371 change_address (addr, Pmode,
2372 plus_constant (XEXP (addr, 0),
2373 fixed * UNITS_PER_WORD)),
2376 /* Return the address of the va_list constructor, but don't put it in a
2377 register. This fails when not optimizing and produces worse code when
2379 return XEXP (block, 0);
2382 /* If cmpsi has not been generated, emit code to do the test. Return the
2383 expression describing the test of operator OP. */
2386 emit_test (op, mode)
2388 enum machine_mode mode;
2390 if (m88k_compare_reg == 0)
2391 emit_insn (gen_test (m88k_compare_op0, m88k_compare_op1));
2392 return (gen_rtx (op, mode, m88k_compare_reg, const0_rtx));
2395 /* Determine how to best perform cmpsi/bxx, where cmpsi has a constant
2396 operand. All tests with zero (albeit swapped) and all equality tests
2397 with a constant are done with bcnd. The remaining cases are swapped
2401 emit_bcnd (op, label)
2405 if (m88k_compare_op1 == const0_rtx)
2406 emit_jump_insn (optimize
2407 ? gen_bxx (emit_test (op, VOIDmode), label)
2408 : gen_bcnd (gen_rtx (op, VOIDmode,
2409 m88k_compare_op0, const0_rtx),
2411 else if (m88k_compare_op0 == const0_rtx)
2412 emit_jump_insn (optimize
2413 ? gen_bxx (emit_test (op, VOIDmode), label)
2414 : gen_bcnd (gen_rtx (swap_condition (op), VOIDmode,
2415 m88k_compare_op1, const0_rtx),
2417 else if (op != EQ && op != NE)
2418 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2421 rtx zero = gen_reg_rtx (SImode);
2425 if (GET_CODE (m88k_compare_op1) == CONST_INT)
2427 reg = force_reg (SImode, m88k_compare_op0);
2428 constant = m88k_compare_op1;
2432 reg = force_reg (SImode, m88k_compare_op1);
2433 constant = m88k_compare_op0;
2435 value = INTVAL (constant);
2437 /* Perform an arithmetic computation to make the compared-to value
2438 zero, but avoid loosing if the bcnd is later changed into sxx. */
2439 if (SMALL_INTVAL (value))
2440 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2443 if (SMALL_INTVAL (-value))
2444 emit_insn (gen_addsi3 (zero, reg,
2445 gen_rtx (CONST_INT, VOIDmode, -value)));
2447 emit_insn (gen_xorsi3 (zero, reg, constant));
2449 emit_jump_insn (gen_bcnd (gen_rtx (op, VOIDmode,
2456 /* Print an operand. Recognize special options, documented below. */
2459 print_operand (file, x, code)
2464 enum rtx_code xc = (x ? GET_CODE (x) : UNKNOWN);
2465 register int value = (xc == CONST_INT ? INTVAL (x) : 0);
2466 static int sequencep;
2467 static int reversep;
2471 if (code < 'B' || code > 'E')
2472 output_operand_lossage ("%R not followed by %B/C/D/E");
2474 xc = reverse_condition (xc);
2480 case '*': /* addressing base register for PIC */
2481 fputs (reg_names[PIC_OFFSET_TABLE_REGNUM], file); return;
2483 case '#': /* SVR4 pound-sign syntax character (empty if SVR3) */
2484 fputs (m88k_pound_sign, file); return;
2486 case 'X': /* print the upper 16 bits... */
2488 case 'x': /* print the lower 16 bits of the integer constant in hex */
2489 if (xc != CONST_INT)
2490 output_operand_lossage ("invalid %x/X value");
2491 fprintf (file, "0x%x", value & 0xffff); return;
2493 case 'H': /* print the low 16 bits of the negated integer constant */
2494 if (xc != CONST_INT)
2495 output_operand_lossage ("invalid %H value");
2497 case 'h': /* print the register or low 16 bits of the integer constant */
2500 if (xc != CONST_INT)
2501 output_operand_lossage ("invalid %h value");
2502 fprintf (file, "%d", value & 0xffff);
2505 case 'Q': /* print the low 8 bits of the negated integer constant */
2506 if (xc != CONST_INT)
2507 output_operand_lossage ("invalid %Q value");
2509 case 'q': /* print the register or low 8 bits of the integer constant */
2512 if (xc != CONST_INT)
2513 output_operand_lossage ("invalid %q value");
2514 fprintf (file, "%d", value & 0xff);
2517 case 'w': /* print the integer constant (X == 32 ? 0 : 32 - X) */
2518 if (xc != CONST_INT)
2519 output_operand_lossage ("invalid %o value");
2520 fprintf (file, "%d", value == 32 ? 0 : 32 - value);
2523 case 'p': /* print the logarithm of the integer constant */
2525 || (value = exact_log2 (value)) < 0)
2526 output_operand_lossage ("invalid %p value");
2527 fprintf (file, "%d", value);
2530 case 'S': /* compliment the value and then... */
2532 case 's': /* print the width and offset values forming the integer
2533 constant with a SET instruction. See integer_ok_for_set. */
2535 register unsigned mask, uval = value;
2536 register int top, bottom;
2538 if (xc != CONST_INT)
2539 output_operand_lossage ("invalid %s/S value");
2540 /* All the "one" bits must be contiguous. If so, MASK will be
2541 a power of two or zero. */
2542 mask = (uval | (uval - 1)) + 1;
2543 if (!(uval && POWER_OF_2_or_0 (mask)))
2544 output_operand_lossage ("invalid %s/S value");
2545 top = mask ? exact_log2 (mask) : 32;
2546 bottom = exact_log2 (uval & ~(uval - 1));
2547 fprintf (file,"%d<%d>", top - bottom, bottom);
2551 case 'P': /* print nothing if pc_rtx; output label_ref */
2552 if (xc == LABEL_REF)
2553 output_addr_const (file, x);
2555 output_operand_lossage ("invalid %P operand");
2558 case 'L': /* print 0 or 1 if operand is label_ref and then... */
2559 fputc (xc == LABEL_REF ? '1' : '0', file);
2560 case '.': /* print .n if delay slot is used */
2561 fputs ((final_sequence
2562 && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
2563 ? ".n\t" : "\t", file);
2566 case 'R': /* reverse the condition of the next print_operand
2567 if operand is a label_ref. */
2569 reversep = (xc == LABEL_REF);
2572 case 'B': /* bcnd branch values */
2573 fputs (m88k_pound_sign, file);
2576 case EQ: fputs ("eq0", file); return;
2577 case NE: fputs ("ne0", file); return;
2578 case GT: fputs ("gt0", file); return;
2579 case LE: fputs ("le0", file); return;
2580 case LT: fputs ("lt0", file); return;
2581 case GE: fputs ("ge0", file); return;
2582 default: output_operand_lossage ("invalid %B value");
2585 case 'C': /* bb0/bb1 branch values for comparisons */
2586 fputs (m88k_pound_sign, file);
2589 case EQ: fputs ("eq", file); return;
2590 case NE: fputs ("ne", file); return;
2591 case GT: fputs ("gt", file); return;
2592 case LE: fputs ("le", file); return;
2593 case LT: fputs ("lt", file); return;
2594 case GE: fputs ("ge", file); return;
2595 case GTU: fputs ("hi", file); return;
2596 case LEU: fputs ("ls", file); return;
2597 case LTU: fputs ("lo", file); return;
2598 case GEU: fputs ("hs", file); return;
2599 default: output_operand_lossage ("invalid %C value");
2602 case 'D': /* bcnd branch values for float comparisons */
2605 case EQ: fputs ("0xa", file); return;
2606 case NE: fputs ("0x5", file); return;
2607 case GT: fputs (m88k_pound_sign, file);
2608 fputs ("gt0", file); return;
2609 case LE: fputs ("0xe", file); return;
2610 case LT: fputs ("0x4", file); return;
2611 case GE: fputs ("0xb", file); return;
2612 default: output_operand_lossage ("invalid %D value");
2615 case 'E': /* bcnd branch values for special integers */
2618 case EQ: fputs ("0x8", file); return;
2619 case NE: fputs ("0x7", file); return;
2620 default: output_operand_lossage ("invalid %E value");
2623 case 'd': /* second register of a two register pair */
2625 output_operand_lossage ("`%d' operand isn't a register");
2626 fputs (reg_names[REGNO (x) + 1], file);
2629 case 'r': /* an immediate 0 should be represented as `r0' */
2630 if (x == const0_rtx)
2632 fputs (reg_names[0], file);
2636 output_operand_lossage ("invalid %r value");
2642 if (REGNO (x) == ARG_POINTER_REGNUM)
2643 output_operand_lossage ("operand is r0");
2645 fputs (reg_names[REGNO (x)], file);
2647 else if (xc == PLUS)
2650 output_address (XEXP (x, 0));
2651 else if (xc == CONST_DOUBLE)
2652 output_operand_lossage ("operand is const_double");
2654 output_addr_const (file, x);
2657 case 'g': /* append #got_rel as needed */
2658 if (flag_pic && (xc == SYMBOL_REF || xc == LABEL_REF))
2660 output_addr_const (file, x);
2661 fputs ("#got_rel", file);
2666 case 'a': /* (standard), assume operand is an address */
2667 case 'c': /* (standard), assume operand is an immediate value */
2668 case 'l': /* (standard), assume operand is a label_ref */
2669 case 'n': /* (standard), like %c, except negate first */
2671 output_operand_lossage ("invalid code");
2676 print_operand_address (file, addr)
2680 register rtx reg0, reg1, temp;
2682 switch (GET_CODE (addr))
2685 if (REGNO (addr) == ARG_POINTER_REGNUM)
2688 fprintf (file, "%s,%s", reg_names[0], reg_names [REGNO (addr)]);
2692 fprintf (file, "%s,%slo16(",
2693 reg_names[REGNO (XEXP (addr, 0))], m88k_pound_sign);
2694 output_addr_const (file, XEXP (addr, 1));
2699 reg0 = XEXP (addr, 0);
2700 reg1 = XEXP (addr, 1);
2701 if (GET_CODE (reg0) == MULT || GET_CODE (reg0) == CONST_INT)
2708 if ((REG_P (reg0) && REGNO (reg0) == ARG_POINTER_REGNUM)
2709 || (REG_P (reg1) && REGNO (reg1) == ARG_POINTER_REGNUM))
2712 else if (REG_P (reg0))
2715 fprintf (file, "%s,%s",
2716 reg_names [REGNO (reg0)], reg_names [REGNO (reg1)]);
2718 else if (GET_CODE (reg1) == CONST_INT)
2719 fprintf (file, "%s,%d",
2720 reg_names [REGNO (reg0)], INTVAL (reg1));
2722 else if (GET_CODE (reg1) == MULT)
2724 rtx mreg = XEXP (reg1, 0);
2725 if (REGNO (mreg) == ARG_POINTER_REGNUM)
2728 fprintf (file, "%s[%s]", reg_names[REGNO (reg0)],
2729 reg_names[REGNO (mreg)]);
2732 else if (GET_CODE (reg1) == ZERO_EXTRACT)
2734 fprintf (file, "%s,%slo16(",
2735 reg_names[REGNO (reg0)], m88k_pound_sign);
2736 output_addr_const (file, XEXP (reg1, 0));
2742 fprintf (file, "%s,", reg_names[REGNO (reg0)]);
2743 output_addr_const (file, reg1);
2744 fputs ("#got_rel", file);
2754 if (REGNO (XEXP (addr, 0)) == ARG_POINTER_REGNUM)
2757 fprintf (file, "%s[%s]",
2758 reg_names[0], reg_names[REGNO (XEXP (addr, 0))]);
2762 fprintf (file, "%s,%shi16(", reg_names[0], m88k_pound_sign);
2763 output_addr_const (file, XEXP (addr, 0));
2768 fprintf (file, "%s,%d", reg_names[0], INTVAL (addr));
2772 fprintf (file, "%s,", reg_names[0]);
2773 if (SHORT_ADDRESS_P (addr, temp))
2775 fprintf (file, "%siw16(", m88k_pound_sign);
2776 output_addr_const (file, addr);
2780 output_addr_const (file, addr);