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"
41 #include "hard-reg-set.h"
44 extern char *version_string;
45 extern time_t time ();
46 extern char *ctime ();
47 extern int flag_traditional;
48 extern FILE *asm_out_file;
50 static char out_sccs_id[] = "@(#)m88k.c 2.1.2.2 27 Mar 1992 08:37:28";
51 static char tm_sccs_id [] = TM_SCCS_ID;
53 char *m88k_pound_sign = ""; /* Either # for SVR4 or empty for SVR3 */
54 char *m88k_short_data;
56 int m88k_gp_threshold;
57 int m88k_prologue_done = 0; /* Ln directives can now be emitted */
58 int m88k_function_number = 0; /* Counter unique to each function */
59 int m88k_fp_offset = 0; /* offset of frame pointer if used */
60 int m88k_stack_size = 0; /* size of allocated stack (including frame) */
63 rtx m88k_compare_reg; /* cmp output pseudo register */
64 rtx m88k_compare_op0; /* cmpsi operand 0 */
65 rtx m88k_compare_op1; /* cmpsi operand 1 */
67 enum attr_cpu m88k_cpu; /* target cpu */
69 /* Determine what instructions are needed to manufacture the integer VALUE
73 classify_integer (mode, value)
74 enum machine_mode mode;
81 else if (SMALL_INTVAL (value))
83 else if (SMALL_INTVAL (-value))
85 else if (mode == HImode)
87 else if (mode == QImode)
89 else if ((value & 0xffff) == 0)
91 else if (integer_ok_for_set (value))
98 integer_ok_for_set (value)
99 register unsigned value;
101 /* All the "one" bits must be contiguous. If so, MASK + 1 will be
102 a power of two or zero. */
103 register unsigned mask = (value | (value - 1));
104 return (value && POWER_OF_2_or_0 (mask + 1));
108 output_load_const_int (mode, operands)
109 enum machine_mode mode;
112 static char *patterns[] =
120 "or.u %0,%#r0,%X1\n\tor %0,%0,%x1",
123 if (! REG_P (operands[0])
124 || GET_CODE (operands[1]) != CONST_INT)
126 return patterns[classify_integer (mode, INTVAL (operands[1]))];
129 /* These next two routines assume that floating point numbers are represented
130 in a manner which is consistent between host and target machines. */
133 output_load_const_float (operands)
136 /* These can return 0 under some circumstances when cross-compiling. */
137 operands[0] = operand_subword (operands[0], 0, 0, SFmode);
138 operands[1] = operand_subword (operands[1], 0, 0, SFmode);
140 return output_load_const_int (SImode, operands);
144 output_load_const_double (operands)
149 /* These can return zero on some cross-compilers, but there's nothing
150 we can do about it. */
151 latehalf[0] = operand_subword (operands[0], 1, 0, DFmode);
152 latehalf[1] = operand_subword (operands[1], 1, 0, DFmode);
154 operands[0] = operand_subword (operands[0], 0, 0, DFmode);
155 operands[1] = operand_subword (operands[1], 0, 0, DFmode);
157 output_asm_insn (output_load_const_int (SImode, operands), operands);
159 operands[0] = latehalf[0];
160 operands[1] = latehalf[1];
162 return output_load_const_int (SImode, operands);
166 output_load_const_dimode (operands)
171 latehalf[0] = operand_subword (operands[0], 1, 0, DImode);
172 latehalf[1] = operand_subword (operands[1], 1, 0, DImode);
174 operands[0] = operand_subword (operands[0], 0, 0, DImode);
175 operands[1] = operand_subword (operands[1], 0, 0, DImode);
177 output_asm_insn (output_load_const_int (SImode, operands), operands);
179 operands[0] = latehalf[0];
180 operands[1] = latehalf[1];
182 return output_load_const_int (SImode, operands);
185 /* Emit insns to move operands[1] into operands[0].
187 Return 1 if we have written out everything that needs to be done to
188 do the move. Otherwise, return 0 and the caller will emit the move
192 emit_move_sequence (operands, mode)
194 enum machine_mode mode;
196 register rtx operand0 = operands[0];
197 register rtx operand1 = operands[1];
199 /* Handle most common case first: storing into a register. */
200 if (register_operand (operand0, mode))
202 if (register_operand (operand1, mode)
203 || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
204 || GET_CODE (operand1) == HIGH
205 /* Only `general_operands' can come here, so MEM is ok. */
206 || GET_CODE (operand1) == MEM)
208 /* Run this case quickly. */
209 emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
213 else if (GET_CODE (operand0) == MEM)
215 if (register_operand (operand1, mode)
216 || (operand1 == const0_rtx && GET_MODE_SIZE (mode) <= UNITS_PER_WORD))
218 /* Run this case quickly. */
219 emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
222 if (! reload_in_progress && ! reload_completed)
224 operands[0] = validize_mem (operand0);
225 operands[1] = operand1 = force_reg (mode, operand1);
229 /* Simplify the source if we need to. */
230 if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
232 if (GET_CODE (operand1) != CONST_INT
233 && GET_CODE (operand1) != CONST_DOUBLE)
235 rtx temp = ((reload_in_progress || reload_completed)
236 ? operand0 : gen_reg_rtx (Pmode));
237 operands[1] = legitimize_address (flag_pic
238 && symbolic_address_p (operand1),
241 operands[1] = gen_rtx (SUBREG, mode, operands[1], 0);
245 /* Now have insn-emit do whatever it normally does. */
249 /* Return a legitimate reference for ORIG (either an address or a MEM) using
250 the register REG. If PIC and the address is already position-independent,
254 legitimize_address (pic, orig, reg)
259 rtx addr = (GET_CODE (orig) == MEM ? XEXP (orig, 0) : orig);
265 if (GET_CODE (addr) == SYMBOL_REF
266 || GET_CODE (addr) == LABEL_REF)
268 if (reg == 0) abort ();
272 emit_insn (gen_rtx (SET, VOIDmode,
273 reg, gen_rtx (HIGH, SImode, addr)));
274 emit_insn (gen_rtx (SET, VOIDmode,
275 reg, gen_rtx (LO_SUM, SImode, reg, addr)));
278 new = gen_rtx (MEM, Pmode,
279 gen_rtx (PLUS, SImode,
280 pic_offset_table_rtx, addr));
281 current_function_uses_pic_offset_table = 1;
282 RTX_UNCHANGING_P (new) = 1;
284 rtx insn = emit_move_insn (reg, new);
285 /* Put a REG_EQUAL note on this insn, so that it can be optimized
287 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, orig,
292 else if (GET_CODE (addr) == CONST)
296 if (GET_CODE (XEXP (addr, 0)) == PLUS
297 && XEXP (XEXP (addr, 0), 0) == pic_offset_table_rtx)
303 if (GET_CODE (XEXP (addr, 0)) != PLUS) abort ();
305 base = legitimize_address (1, XEXP (XEXP (addr, 0), 0), reg);
306 addr = legitimize_address (1, XEXP (XEXP (addr, 0), 1),
307 base == reg ? 0 : reg);
309 if (GET_CODE (addr) == CONST_INT)
310 new = plus_constant_for_output (base, INTVAL (addr));
312 new = gen_rtx (PLUS, SImode, base, addr);
313 /* Should we set special REG_NOTEs here? */
316 else if (! SHORT_ADDRESS_P (addr, temp))
318 emit_insn (gen_rtx (SET, VOIDmode,
319 reg, gen_rtx (HIGH, SImode, addr)));
320 new = gen_rtx (LO_SUM, SImode, reg, addr);
324 && GET_CODE (orig) == MEM)
326 new = gen_rtx (MEM, GET_MODE (orig), new);
327 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (orig);
328 MEM_VOLATILE_P (new) = MEM_VOLATILE_P (orig);
329 MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (orig);
334 /* Support functions for code to emit a block move. There are four methods
335 used to perform the block move:
337 + call the looping library function, e.g. __movstrSI64n8
338 + call a non-looping library function, e.g. __movstrHI15x11
339 + produce an inline sequence of ld/st instructions
341 The parameters below describe the library functions produced by
344 #define MOVSTR_LOOP 64 /* __movstrSI64n68 .. __movstrSI64n8 */
345 #define MOVSTR_QI 16 /* __movstrQI16x16 .. __movstrQI16x2 */
346 #define MOVSTR_HI 48 /* __movstrHI48x48 .. __movstrHI48x4 */
347 #define MOVSTR_SI 96 /* __movstrSI96x96 .. __movstrSI96x8 */
348 #define MOVSTR_ODD_SI 48 /* __movstrSI47x47 .. __movstrSI47x11,
349 __movstrSI46x46 .. __movstrSI46x10,
350 __movstrSI45x45 .. __movstrSI45x9 */
351 #define MOVSTR_ODD_HI 16 /* __movstrHI15x15 .. __movstrHI15x5 */
353 /* Break even points where memcpy will do just as well. */
354 #define MOVSTR_QI_LIMIT 13
355 #define MOVSTR_HI_LIMIT 38
356 #define MOVSTR_SI_LIMIT MOVSTR_SI
358 static enum machine_mode mode_from_bytes[] =
359 {VOIDmode, QImode, HImode, VOIDmode, SImode};
360 static int max_from_bytes[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI};
361 static int all_from_bytes[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0, MOVSTR_ODD_SI};
362 static int best_from_bytes[] =
363 {0, MOVSTR_QI_LIMIT, MOVSTR_HI_LIMIT, 0, MOVSTR_SI_LIMIT};
365 static void block_move_loop ();
366 static void block_move_no_loop ();
367 static void block_move_sequence ();
369 /* Emit code to perform a block move. Choose the best method.
371 OPERANDS[0] is the destination.
372 OPERANDS[1] is the source.
373 OPERANDS[2] is the size.
374 OPERANDS[3] is the alignment safe to use. */
377 expand_block_move (dest_mem, src_mem, operands)
382 int align = INTVAL (operands[3]);
383 int constp = (GET_CODE (operands[2]) == CONST_INT);
384 int bytes = (constp ? INTVAL (operands[2]) : 0);
386 if (constp && bytes <= 0)
389 /* Determine machine mode to do move with. */
392 else if (align <= 0 || align == 3)
393 abort (); /* block move invalid alignment. */
395 if (constp && bytes <= 3 * align)
396 block_move_sequence (operands[0], dest_mem, operands[1], src_mem,
399 else if (constp && bytes <= best_from_bytes[align])
400 block_move_no_loop (operands[0], dest_mem, operands[1], src_mem,
403 else if (constp && align == 4)
404 block_move_loop (operands[0], dest_mem, operands[1], src_mem,
409 #ifdef TARGET_MEM_FUNCTIONS
410 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"), 0,
414 operands[2], SImode);
416 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcopy"), 0,
420 operands[2], SImode);
425 /* Emit code to perform a block move by calling a looping movstr library
426 function. SIZE and ALIGN are known constants. DEST and SRC are
430 block_move_loop (dest, dest_mem, src, src_mem, size, align)
436 enum machine_mode mode;
445 /* Determine machine mode to do move with. */
449 /* Determine the structure of the loop. */
450 count = size / MOVSTR_LOOP;
451 units = (size - count * MOVSTR_LOOP) / align;
456 units += MOVSTR_LOOP / align;
461 block_move_no_loop (dest, dest_mem, src, src_mem, size, align);
465 remainder = size - count * MOVSTR_LOOP - units * align;
467 mode = mode_from_bytes[align];
468 sprintf (entry, "__movstr%s%dn%d",
469 GET_MODE_NAME (mode), MOVSTR_LOOP, units * align);
470 entry_name = get_identifier (entry);
472 offset_rtx = gen_rtx (CONST_INT, VOIDmode,
473 MOVSTR_LOOP + (1 - units) * align);
475 value_rtx = gen_rtx (MEM, mode,
476 gen_rtx (PLUS, Pmode,
477 gen_rtx (REG, Pmode, 3),
479 RTX_UNCHANGING_P (value_rtx) = RTX_UNCHANGING_P (src_mem);
480 MEM_VOLATILE_P (value_rtx) = MEM_VOLATILE_P (src_mem);
481 MEM_IN_STRUCT_P (value_rtx) = MEM_IN_STRUCT_P (src_mem);
483 emit_insn (gen_call_block_move_loop
484 (gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)),
485 dest, src, offset_rtx, value_rtx,
486 gen_rtx (REG, GET_MODE (value_rtx), ((units & 1) ? 4 : 5)),
487 gen_rtx (CONST_INT, VOIDmode, count)));
490 block_move_sequence (gen_rtx (REG, Pmode, 2), dest_mem,
491 gen_rtx (REG, Pmode, 3), src_mem,
492 remainder, align, MOVSTR_LOOP + align);
495 /* Emit code to perform a block move by calling a non-looping library
496 function. SIZE and ALIGN are known constants. DEST and SRC are
497 registers. OFFSET is the known starting point for the output pattern. */
500 block_move_no_loop (dest, dest_mem, src, src_mem, size, align)
506 enum machine_mode mode = mode_from_bytes[align];
507 int units = size / align;
508 int remainder = size - units * align;
516 if (remainder && size <= all_from_bytes[align])
518 most = all_from_bytes[align] - (align - remainder);
523 most = max_from_bytes[align];
526 sprintf (entry, "__movstr%s%dx%d",
527 GET_MODE_NAME (mode), most, size - remainder);
528 entry_name = get_identifier (entry);
530 offset_rtx = gen_rtx (CONST_INT, VOIDmode, most - (size - remainder));
532 value_rtx = gen_rtx (MEM, mode,
533 gen_rtx (PLUS, Pmode,
534 gen_rtx (REG, Pmode, 3),
536 RTX_UNCHANGING_P (value_rtx) = RTX_UNCHANGING_P (src_mem);
537 MEM_VOLATILE_P (value_rtx) = MEM_VOLATILE_P (src_mem);
538 MEM_IN_STRUCT_P (value_rtx) = MEM_IN_STRUCT_P (src_mem);
540 evenp = ((most - (size - remainder)) / align) & 1;
542 emit_insn (gen_call_block_move
543 (gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)),
544 dest, src, offset_rtx, value_rtx,
545 gen_rtx (REG, GET_MODE (value_rtx), (evenp ? 4 : 5))));
548 block_move_sequence (gen_rtx (REG, Pmode, 2), dest_mem,
549 gen_rtx (REG, Pmode, 3), src_mem,
550 remainder, align, most);
553 /* Emit code to perform a block move with an offset sequence of ld/st
554 instructions (..., ld 0, st 1, ld 1, st 0, ...). SIZE and ALIGN are
555 known constants. DEST and SRC are registers. OFFSET is the known
556 starting point for the output pattern. */
559 block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset)
567 enum machine_mode mode[2];
572 int offset_ld = offset;
573 int offset_st = offset;
575 active[0] = active[1] = FALSE;
577 /* Establish parameters for the first load and for the second load if
578 it is known to be the same mode as the first. */
579 amount[0] = amount[1] = align;
580 mode[0] = mode_from_bytes[align];
581 temp[0] = gen_reg_rtx (mode[0]);
582 if (size >= 2 * align)
585 temp[1] = gen_reg_rtx (mode[1]);
596 /* Change modes as the sequence tails off. */
597 if (size < amount[next])
599 amount[next] = (size >= 2 ? 2 : 1);
600 mode[next] = mode_from_bytes[amount[next]];
601 temp[next] = gen_reg_rtx (mode[next]);
603 size -= amount[next];
604 srcp = gen_rtx (MEM, mode[next],
605 gen_rtx (PLUS, Pmode, src,
606 gen_rtx (CONST_INT, SImode, offset_ld)));
607 RTX_UNCHANGING_P (srcp) = RTX_UNCHANGING_P (src_mem);
608 MEM_VOLATILE_P (srcp) = MEM_VOLATILE_P (src_mem);
609 MEM_IN_STRUCT_P (srcp) = MEM_IN_STRUCT_P (src_mem);
610 emit_move_insn (temp[next], srcp);
611 offset_ld += amount[next];
617 active[phase] = FALSE;
618 dstp = gen_rtx (MEM, mode[phase],
619 gen_rtx (PLUS, Pmode, dest,
620 gen_rtx (CONST_INT, SImode, offset_st)));
621 RTX_UNCHANGING_P (dstp) = RTX_UNCHANGING_P (dest_mem);
622 MEM_VOLATILE_P (dstp) = MEM_VOLATILE_P (dest_mem);
623 MEM_IN_STRUCT_P (dstp) = MEM_IN_STRUCT_P (dest_mem);
624 emit_move_insn (dstp, temp[phase]);
625 offset_st += amount[phase];
628 while (active[next]);
631 /* Emit the code to do an AND operation. */
634 output_and (operands)
639 if (REG_P (operands[2]))
640 return "and %0,%1,%2";
642 value = INTVAL (operands[2]);
643 if (SMALL_INTVAL (value))
644 return "mask %0,%1,%2";
645 else if ((value & 0xffff0000) == 0xffff0000)
646 return "and %0,%1,%x2";
647 else if ((value & 0xffff) == 0xffff)
648 return "and.u %0,%1,%X2";
649 else if ((value & 0xffff) == 0)
650 return "mask.u %0,%1,%X2";
651 else if (integer_ok_for_set (~value))
652 return "clr %0,%1,%S2";
654 return "and.u %0,%1,%X2\n\tand %0,%0,%x2";
657 /* Emit the code to do an inclusive OR operation. */
660 output_ior (operands)
665 if (REG_P (operands[2]))
666 return "or %0,%1,%2";
668 value = INTVAL (operands[2]);
669 if (SMALL_INTVAL (value))
670 return "or %0,%1,%2";
671 else if ((value & 0xffff) == 0)
672 return "or.u %0,%1,%X2";
673 else if (integer_ok_for_set (value))
674 return "set %0,%1,%s2";
676 return "or.u %0,%1,%X2\n\tor %0,%0,%x2";
679 /* Emit the instructions for doing an XOR. */
682 output_xor (operands)
687 if (REG_P (operands[2]))
688 return "xor %0,%1,%2";
690 value = INTVAL (operands[2]);
691 if (SMALL_INTVAL (value))
692 return "xor %0,%1,%2";
693 else if ((value & 0xffff) == 0)
694 return "xor.u %0,%1,%X2";
696 return "xor.u %0,%1,%X2\n\txor %0,%0,%x2";
699 /* Output a call. Normally this is just bsr or jsr, but this also deals with
700 accomplishing a branch after the call by incrementing r1. This requires
701 that various assembler bugs be accommodated. The 4.30 DG/UX assembler
702 requires that forward references not occur when computing the difference of
703 two labels. The [version?] Motorola assembler computes a word difference.
704 No doubt there's more to come!
706 It would seem the same idea could be used to tail call, but in this case,
707 the epilogue will be non-null. */
709 static rtx sb_name = 0;
710 static rtx sb_high = 0;
711 static rtx sb_low = 0;
714 output_call (operands, addr)
723 /* This can be generalized, but there is currently no need. */
724 if (XVECLEN (final_sequence, 0) != 2)
727 jump = XVECEXP (final_sequence, 0, 1);
728 if (GET_CODE (jump) == JUMP_INSN)
732 rtx dest = XEXP (SET_SRC (PATTERN (jump)), 0);
733 int delta = 4 * (insn_addresses[INSN_UID (dest)]
734 - insn_addresses[INSN_UID (jump)]);
735 #if (MONITOR_GCC & 0x2) /* How often do long branches happen? */
736 if ((unsigned) (delta + 0x8000) >= 0x10000)
737 warning ("Internal gcc monitor: short-branch(%x)", delta);
740 /* Delete the jump. */
741 PUT_CODE (jump, NOTE);
742 NOTE_LINE_NUMBER (jump) = NOTE_INSN_DELETED;
743 NOTE_SOURCE_FILE (jump) = 0;
745 /* If we loose, we must use the non-delay form. This is unlikely
746 to ever happen. If it becomes a problem, claim that a call
747 has two delay slots and only the second can be filled with
749 #ifdef AS_BUG_IMMEDIATE_LABEL /* The assembler restricts immediate values. */
750 if (! ADD_INTVAL (delta * 2))
752 if (! ADD_INTVAL (delta))
759 ? "bsr %0#plt\n\tbr %l1"
760 : "bsr %0\n\tbr %l1"));
763 /* Output the short branch form. */
764 output_asm_insn ((REG_P (addr)
766 : (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")),
769 operands[0] = gen_label_rtx ();
770 operands[1] = gen_label_rtx ();
775 last = "subu %#r1,%#r1,%l0\n%l1:";
781 last = "addu %#r1,%#r1,%l0\n%l1:";
784 /* Record the values to be computed later as "def name,high-low". */
785 sb_name = gen_rtx (EXPR_LIST, VOIDmode, operands[0], sb_name);
786 sb_high = gen_rtx (EXPR_LIST, VOIDmode, high, sb_high);
787 sb_low = gen_rtx (EXPR_LIST, VOIDmode, low, sb_low);
794 : (flag_pic ? "bsr%. %0#plt" : "bsr%. %0"));
798 output_short_branch_defs (stream)
801 char name[256], high[256], low[256];
803 for (; sb_name && sb_high && sb_low;
804 sb_name = XEXP (sb_name, 1),
805 sb_high = XEXP (sb_high, 1),
806 sb_low = XEXP (sb_low, 1))
808 ASM_GENERATE_INTERNAL_LABEL
809 (name, "L", CODE_LABEL_NUMBER (XEXP (sb_name, 0)));
810 ASM_GENERATE_INTERNAL_LABEL
811 (high, "L", CODE_LABEL_NUMBER (XEXP (sb_high, 0)));
812 ASM_GENERATE_INTERNAL_LABEL
813 (low, "L", CODE_LABEL_NUMBER (XEXP (sb_low, 0)));
814 /* This will change as the assembler requirements become known. */
815 fprintf (stream, "\t%s\t %s,%s-%s\n",
816 DEF_ASM_OP, &name[1], &high[1], &low[1]);
818 if (sb_name || sb_high || sb_low)
822 /* Report errors on floating point, if we are given NaN's, or such. Leave
823 the number as is, though, since we output the number in hex, and the
824 assembler won't choke on it. */
827 check_float_value (mode, value)
828 enum machine_mode mode;
829 REAL_VALUE_TYPE value;
835 unsigned exponent : 11;
836 unsigned mantissa1 : 20;
844 if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0)
846 if (u.s.exponent == 0x7ff) /* Not a Number */
847 warning ("floating point number is not valid for IEEE double precision");
848 else if (u.s.exponent == 0)
849 warning ("denormalized double precision floating point number");
852 else if (mode == SFmode)
854 u.d = REAL_VALUE_TRUNCATE (mode, value);
855 if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0)
857 if (u.s.exponent == 0x7ff) /* Not a Number */
858 warning ("floating point number is not valid for IEEE double precision");
859 else if (u.s.exponent == 0)
860 warning ("denormalized single precision floating point number");
862 else if (u.s.exponent == 0x7ff) /* Infinity */
863 warning ("floating point number exceeds range of `float'");
867 /* Return true if the operand is a power of two and is a floating
868 point type (to optimize division by power of two into multiplication). */
871 real_power_of_2_operand (op, mode)
873 enum machine_mode mode;
877 int i[sizeof (REAL_VALUE_TYPE) / sizeof (int)];
878 struct { /* IEEE double precision format */
880 unsigned exponent : 11;
881 unsigned mantissa1 : 20;
884 struct { /* IEEE double format to quick check */
885 unsigned sign : 1; /* if it fits in a float */
886 unsigned exponent1 : 4;
887 unsigned exponent2 : 7;
888 unsigned mantissa1 : 20;
893 if (GET_MODE (op) != DFmode && GET_MODE (op) != SFmode)
896 if (GET_CODE (op) != CONST_DOUBLE)
899 u.i[0] = CONST_DOUBLE_LOW (op);
900 u.i[1] = CONST_DOUBLE_HIGH (op);
902 if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0 /* not a power of two */
903 || u.s.exponent == 0 /* constant 0.0 */
904 || u.s.exponent == 0x7ff /* NAN */
905 || (u.s2.exponent1 != 0x8 && u.s2.exponent1 != 0x7))
906 return 0; /* const won't fit in float */
911 /* Make OP legitimate for mode MODE. Currently this only deals with DFmode
912 operands, putting them in registers and making CONST_DOUBLE values
913 SFmode where possible. */
916 legitimize_operand (op, mode)
918 enum machine_mode mode;
922 union real_extract r;
923 struct { /* IEEE double precision format */
925 unsigned exponent : 11;
926 unsigned mantissa1 : 20;
929 struct { /* IEEE double format to quick check */
930 unsigned sign : 1; /* if it fits in a float */
931 unsigned exponent1 : 4;
932 unsigned exponent2 : 7;
933 unsigned mantissa1 : 20;
938 if (GET_CODE (op) == REG || mode != DFmode)
941 if (GET_CODE (op) == CONST_DOUBLE)
943 bcopy (&CONST_DOUBLE_LOW (op), &u.r, sizeof u);
944 if (u.d.exponent != 0x7ff /* NaN */
945 && u.d.mantissa2 == 0 /* Mantissa fits */
946 && (u.s.exponent1 == 0x8 || u.s.exponent1 == 0x7) /* Exponent fits */
947 && (temp = simplify_unary_operation (FLOAT_TRUNCATE, SFmode,
949 return gen_rtx (FLOAT_EXTEND, mode, force_reg (SFmode, temp));
951 else if (register_operand (op, mode))
954 return force_reg (mode, op);
957 /* Return true if OP is a suitable input for a move insn. */
960 move_operand (op, mode)
962 enum machine_mode mode;
964 if (register_operand (op, mode))
966 if (GET_CODE (op) == CONST_INT)
967 return (classify_integer (mode, INTVAL (op)) < m88k_oru_hi16);
968 if (GET_MODE (op) != mode)
970 if (GET_CODE (op) == SUBREG)
971 op = SUBREG_REG (op);
972 if (GET_CODE (op) != MEM)
976 if (GET_CODE (op) == LO_SUM)
977 return (REG_P (XEXP (op, 0))
978 && symbolic_address_p (XEXP (op, 1)));
979 return memory_address_p (mode, op);
982 /* Return true if OP is suitable for a call insn. */
985 call_address_operand (op, mode)
987 enum machine_mode mode;
989 return (REG_P (op) || symbolic_address_p (op));
992 /* Returns true if OP is either a symbol reference or a sum of a symbol
993 reference and a constant. */
996 symbolic_address_p (op)
999 switch (GET_CODE (op))
1007 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1008 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1009 && GET_CODE (XEXP (op, 1)) == CONST_INT);
1016 /* Return true if OP is a register or const0_rtx. */
1019 reg_or_0_operand (op, mode)
1021 enum machine_mode mode;
1023 return (op == const0_rtx || register_operand (op, mode));
1026 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
1029 arith_operand (op, mode)
1031 enum machine_mode mode;
1033 return (register_operand (op, mode)
1034 || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
1037 /* Return true if OP is a register or 5 bit integer. */
1040 arith5_operand (op, mode)
1042 enum machine_mode mode;
1044 return (register_operand (op, mode)
1045 || (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32));
1049 arith32_operand (op, mode)
1051 enum machine_mode mode;
1053 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
1057 arith64_operand (op, mode)
1059 enum machine_mode mode;
1061 return (register_operand (op, mode)
1062 || GET_CODE (op) == CONST_INT
1063 || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DImode));
1067 int5_operand (op, mode)
1069 enum machine_mode mode;
1071 return (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32);
1075 int32_operand (op, mode)
1077 enum machine_mode mode;
1079 return (GET_CODE (op) == CONST_INT);
1082 /* Return true if OP is a register or a valid immediate operand for
1086 add_operand (op, mode)
1088 enum machine_mode mode;
1090 return (register_operand (op, mode)
1091 || (GET_CODE (op) == CONST_INT && ADD_INT (op)));
1094 /* Nonzero if this is a bitmask filling the bottom bits, for optimizing and +
1095 shift left combinations into a single mak instruction. */
1101 return (value && POWER_OF_2_or_0 (value + 1));
1105 reg_or_bbx_mask_operand (op, mode)
1107 enum machine_mode mode;
1110 if (register_operand (op, mode))
1112 if (GET_CODE (op) != CONST_INT)
1115 value = INTVAL (op);
1116 if (POWER_OF_2 (value))
1122 /* Return true if OP is valid to use in the context of a floating
1123 point operation. Special case 0.0, since we can use r0. */
1126 real_or_0_operand (op, mode)
1128 enum machine_mode mode;
1130 if (mode != SFmode && mode != DFmode)
1133 return (register_operand (op, mode)
1134 || (GET_CODE (op) == CONST_DOUBLE
1135 && op == CONST0_RTX (mode)));
1138 /* Return true if OP is a relational operator. */
1143 enum machine_mode mode;
1145 switch (GET_CODE (op))
1163 /* Return true if OP is a relational operator, and is not an unsigned
1164 relational operator. */
1167 relop_no_unsigned (op, mode)
1169 enum machine_mode mode;
1171 switch (GET_CODE (op))
1179 /* @@ What is this test doing? Why not use `mode'? */
1180 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
1181 || GET_MODE (op) == DImode
1182 || GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_FLOAT
1183 || GET_MODE (XEXP (op, 0)) == DImode
1184 || GET_MODE_CLASS (GET_MODE (XEXP (op, 1))) == MODE_FLOAT
1185 || GET_MODE (XEXP (op, 1)) == DImode)
1193 /* Return true if the code of this rtx pattern is EQ or NE. */
1196 equality_op (op, mode)
1198 enum machine_mode mode;
1200 return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
1203 /* Return true if the code of this rtx pattern is pc or label_ref. */
1206 pc_or_label_ref (op, mode)
1208 enum machine_mode mode;
1210 return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF);
1213 /* Output to FILE the start of the assembler file. */
1223 output_option (file, sep, type, name, indent, pos, max)
1232 if (strlen (sep) + strlen (type) + strlen (name) + pos > max)
1234 fprintf (file, indent);
1235 return fprintf (file, "%s%s", type, name);
1237 return pos + fprintf (file, "%s%s%s", sep, type, name);
1240 static struct { char *name; int value; } m_options[] = TARGET_SWITCHES;
1243 output_options (file, f_options, f_len, W_options, W_len,
1244 pos, max, sep, indent, term)
1246 struct option *f_options;
1247 struct option *W_options;
1257 pos = output_option (file, sep, "-O", "", indent, pos, max);
1258 if (write_symbols != NO_DEBUG)
1259 pos = output_option (file, sep, "-g", "", indent, pos, max);
1260 if (flag_traditional)
1261 pos = output_option (file, sep, "-traditional", "", indent, pos, max);
1263 pos = output_option (file, sep, "-p", "", indent, pos, max);
1265 for (j = 0; j < f_len; j++)
1266 if (*f_options[j].variable == f_options[j].on_value)
1267 pos = output_option (file, sep, "-f", f_options[j].string,
1270 for (j = 0; j < W_len; j++)
1271 if (*W_options[j].variable == W_options[j].on_value)
1272 pos = output_option (file, sep, "-W", W_options[j].string,
1275 for (j = 0; j < sizeof m_options / sizeof m_options[0]; j++)
1276 if (m_options[j].name[0] != '\0'
1277 && m_options[j].value > 0
1278 && ((m_options[j].value & target_flags)
1279 == m_options[j].value))
1280 pos = output_option (file, sep, "-m", m_options[j].name,
1283 if (m88k_short_data)
1284 pos = output_option (file, sep, "-mshort-data-", m88k_short_data,
1287 fprintf (file, term);
1291 output_file_start (file, f_options, f_len, W_options, W_len)
1293 struct option *f_options;
1294 struct option *W_options;
1299 ASM_FIRST_LINE (file);
1300 output_file_directive (file, main_input_filename);
1301 /* Switch to the data section so that the coffsem symbol and the
1302 gcc2_compiled. symbol aren't in the text section. */
1306 pos = fprintf (file, "\n; cc1 (%s) arguments:", VERSION_STRING);
1307 output_options (file, f_options, f_len, W_options, W_len,
1308 pos, 75, " ", "\n; ", "\n\n");
1310 if (TARGET_IDENTIFY_REVISION)
1314 time_t now = time ((time_t *)0);
1315 sprintf (indent, "]\"\n\t%s\t \"@(#)%s [", IDENT_ASM_OP, main_input_filename);
1316 fprintf (file, indent+3);
1317 pos = fprintf (file, "gcc %s, %.24s,", VERSION_STRING, ctime (&now));
1318 output_options (file, f_options, f_len, W_options, W_len,
1319 pos, 150 - strlen (indent), " ", indent, "]\"\n\n");
1323 /* Output an ascii string. */
1326 output_ascii (file, p, size)
1333 register int num = 0;
1335 fprintf (file, "\t%s\t \"", ASCII_DATA_ASM_OP);
1336 for (i = 0; i < size; i++)
1338 register int c = p[i];
1342 fprintf (file, "\"\n\t%s\t \"", ASCII_DATA_ASM_OP);
1346 if (c == '\"' || c == '\\')
1352 if (c >= ' ' && c < 0177)
1359 fprintf (file, "\\%03o", c);
1361 /* After an octal-escape, if a digit follows,
1362 terminate one string constant and start another.
1363 The Vax assembler fails to stop reading the escape
1364 after three digits, so this is the only way we
1365 can get it to parse the data properly. */
1366 if (i < size - 1 && p[i + 1] >= '0' && p[i + 1] <= '9')
1367 num = 32767; /* next pass will start a new string */
1370 fprintf (file, "\"\n");
1373 /* Output a label (allows insn-output.c to be compiled without including
1374 m88k.c or needing to include stdio.h). */
1377 output_label (label_number)
1380 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", label_number);
1383 /* Handle a pragma directive. HANDLE_PRAGMA conspires to parse the input
1384 following #pragma into tokens based on yylex. */
1387 m88k_handle_pragma_token (string, token)
1391 static enum pragma_state
1404 if (HANDLE_PRAGMA_WEAK)
1408 if (state == ps_name || state == ps_value)
1410 fprintf (asm_out_file, "\t%s\t ", WEAK_ASM_OP);
1411 ASM_OUTPUT_LABELREF (asm_out_file, name);
1412 fputc ('\n', asm_out_file);
1413 if (state == ps_value)
1415 fprintf (asm_out_file, "\t%s\t ", DEF_ASM_OP);
1416 ASM_OUTPUT_LABELREF (asm_out_file, name);
1417 fputc (',', asm_out_file);
1418 ASM_OUTPUT_LABELREF (asm_out_file, value);
1419 fputc ('\n', asm_out_file);
1422 else if (! (state == ps_done || state == ps_start))
1423 warning ("ignoring malformed #pragma weak symbol [=value]");
1431 && TREE_CODE (token) == IDENTIFIER_NODE
1432 && !strcmp (IDENTIFIER_POINTER (token), "weak"))
1440 && TREE_CODE (token) == IDENTIFIER_NODE)
1442 name = IDENTIFIER_POINTER (token);
1450 state = (strcmp (string, "=") ? ps_bad : ps_equals);
1455 && TREE_CODE (token) == IDENTIFIER_NODE)
1457 value = IDENTIFIER_POINTER (token);
1476 /* Generate the assembly code for function entry.
1478 The prologue is responsible for setting up the stack frame,
1479 initializing the frame pointer register, saving registers that must be
1480 saved, and allocating SIZE additional bytes of storage for the
1481 local variables. SIZE is an integer. FILE is a stdio
1482 stream to which the assembler code should be output.
1484 The label for the beginning of the function need not be output by this
1485 macro. That has already been done when the macro is run.
1487 To determine which registers to save, the macro can refer to the array
1488 `regs_ever_live': element R is nonzero if hard register
1489 R is used anywhere within the function. This implies the
1490 function prologue should save register R, but not if it is one
1491 of the call-used registers.
1493 On machines where functions may or may not have frame-pointers, the
1494 function entry code must vary accordingly; it must set up the frame
1495 pointer if one is wanted, and not otherwise. To determine whether a
1496 frame pointer is in wanted, the macro can refer to the variable
1497 `frame_pointer_needed'. The variable's value will be 1 at run
1498 time in a function that needs a frame pointer.
1500 On machines where an argument may be passed partly in registers and
1501 partly in memory, this macro must examine the variable
1502 `current_function_pretend_args_size', and allocate that many bytes
1503 of uninitialized space on the stack just underneath the first argument
1504 arriving on the stack. (This may not be at the very end of the stack,
1505 if the calling sequence has pushed anything else since pushing the stack
1506 arguments. But usually, on such machines, nothing else has been pushed
1507 yet, because the function prologue itself does all the pushing.)
1509 If `ACCUMULATE_OUTGOING_ARGS' is defined, the variable
1510 `current_function_outgoing_args_size' contains the size in bytes
1511 required for the outgoing arguments. This macro must add that
1512 amount of uninitialized space to very bottom of the stack.
1514 The stack frame we use looks like this:
1517 |==============================================|
1519 |==============================================|
1520 | [caller's outgoing memory arguments] |
1521 |==============================================|
1522 | caller's outgoing argument area (32 bytes) |
1523 sp -> |==============================================| <- ap
1524 | [local variable space] |
1525 |----------------------------------------------|
1526 | [return address (r1)] |
1527 |----------------------------------------------|
1528 | [previous frame pointer (r30)] |
1529 |==============================================| <- fp
1530 | [preserved registers (r25..r14)] |
1531 |==============================================|
1532 | [dynamically allocated space (alloca)] |
1533 |==============================================|
1534 | [callee's outgoing memory arguments] |
1535 |==============================================|
1536 | [callee's outgoing argument area (32 bytes)] |
1537 |==============================================| <- sp
1541 r1 and r30 must be saved if debugging.
1543 fp (if present) is located two words down from the local
1547 static void output_reg_adjust ();
1548 static void preserve_registers ();
1549 static void output_tdesc ();
1552 static char save_regs[FIRST_PSEUDO_REGISTER];
1553 static int frame_laid_out;
1554 static int frame_size;
1555 static int variable_args_p;
1557 extern char call_used_regs[];
1558 extern int current_function_pretend_args_size;
1559 extern int current_function_outgoing_args_size;
1560 extern int frame_pointer_needed;
1562 #define FIRST_OCS_PRESERVE_REGISTER 14
1563 #define LAST_OCS_PRESERVE_REGISTER 30
1565 #define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
1566 #define ROUND_CALL_BLOCK_SIZE(BYTES) \
1567 (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
1569 /* Establish the position of the FP relative to the SP. This is done
1570 either during FUNCTION_PROLOGUE or by INITIAL_ELIMINATION_OFFSET. */
1573 m88k_layout_frame ()
1579 bzero ((char *) &save_regs[0], sizeof (save_regs));
1580 sp_size = nregs = 0;
1581 frame_size = get_frame_size ();
1583 /* Since profiling requires a call, make sure r1 is saved. */
1587 /* If we are producing debug information, store r1 and r30 where the
1588 debugger wants to find them (r30 at r30+0, r1 at r30+4). Space has
1589 already been reserved for r1/r30 in STARTING_FRAME_OFFSET. */
1590 if (write_symbols != NO_DEBUG && !TARGET_OCS_FRAME_POSITION)
1593 /* If there is a call, alloca is used, __builtin_alloca is used, or
1594 a dynamic-sized object is defined, add the 8 additional words
1595 for the callee's argument area. The common denominator is that the
1596 FP is required. may_call_alloca only gets calls to alloca;
1597 current_function_calls_alloca gets alloca and __builtin_alloca. */
1598 if (regs_ever_live[1] || frame_pointer_needed)
1601 sp_size += REG_PARM_STACK_SPACE (0);
1604 /* If we are producing PIC, save the addressing base register and r1. */
1605 if (flag_pic && current_function_uses_pic_offset_table)
1607 save_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
1611 /* If a frame is requested, save the previous FP, and the return
1612 address (r1), so that a traceback can be done without using tdesc
1614 if (frame_pointer_needed)
1615 save_regs[FRAME_POINTER_REGNUM] = save_regs[1] = 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 regsters 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 sp_size += 4 * nregs;
1632 sp_size += current_function_outgoing_args_size;
1634 /* The first two saved registers are placed above the new frame pointer
1635 if any. In the only case this matters, they are r1 and r30. */
1636 if (frame_pointer_needed || sp_size)
1638 m88k_fp_offset = ROUND_CALL_BLOCK_SIZE (sp_size - STARTING_FRAME_OFFSET);
1639 m88k_stack_size = m88k_fp_offset + STARTING_FRAME_OFFSET;
1643 m88k_stack_size = m88k_fp_offset = 0;
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
1678 && m88k_stack_size == 0);
1681 /* Determine the number of instructions needed for the function epilogue. */
1683 #define MAX_EPILOGUE_DELAY_INSNS 4
1685 static char epilogue_dead_regs[FIRST_PSEUDO_REGISTER];
1687 delay_slots_for_epilogue ()
1689 register int insns = save_regs[1] + save_regs[FRAME_POINTER_REGNUM];
1690 register int regs = nregs - insns;
1693 insns += 1 + (regs & 1);
1694 else if (nregs == 4)
1695 /* This is a special cases of ld/ld/ld.d which has no start-up delay. */
1700 bzero ((char *) &epilogue_dead_regs[0], sizeof (epilogue_dead_regs));
1701 epilogue_dead_regs[1] = save_regs[1];
1702 epilogue_dead_regs[STACK_POINTER_REGNUM] = frame_pointer_needed;
1703 epilogue_dead_regs[TEMP_REGNUM] = ! ADD_INTVAL (m88k_fp_offset);
1709 /* Return 1 if X is safe to use as an epilogue insn. */
1712 ok_for_epilogue_p (x)
1718 switch (GET_CODE (x))
1721 for (i = REGNO (x), j = i + HARD_REGNO_NREGS (i, GET_MODE (x));
1724 if (epilogue_dead_regs[i])
1738 fmt = GET_RTX_FORMAT (GET_CODE (x));
1739 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
1743 if (!ok_for_epilogue_p (XEXP (x, i)))
1746 else if (fmt[i] == 'E')
1748 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1749 if (!ok_for_epilogue_p (XVECEXP (x, i, j)))
1757 eligible_for_epilogue_delay (insn)
1760 switch (get_attr_type (insn))
1767 return ok_for_epilogue_p (PATTERN (insn));
1773 /* Determine if the current function has any references to the arg pointer.
1774 This is done indirectly by examining the DECL_ARGUMENTS' DECL_RTL.
1775 It is OK to return TRUE if there are no references, but FALSE must be
1783 if (current_function_decl == 0
1784 || current_function_varargs
1788 for (parm = DECL_ARGUMENTS (current_function_decl);
1790 parm = TREE_CHAIN (parm))
1792 if (DECL_RTL (parm) == 0
1793 || GET_CODE (DECL_RTL (parm)) == MEM)
1796 if (DECL_INCOMING_RTL (parm) == 0
1797 || GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
1804 m88k_output_prologue (stream, size)
1808 int old_fp_offset = m88k_fp_offset;
1809 int old_stack_size = m88k_stack_size;
1811 m88k_layout_frame ();
1812 #if (MONITOR_GCC & 0x8) /* Watch for suspicious register elimination changes. */
1813 if (frame_laid_out > 1)
1815 if (old_fp_offset != m88k_fp_offset)
1816 warning ("Internal gcc error: FP offset has changed by %d bytes",
1817 m88k_fp_offset - old_fp_offset);
1818 if (old_stack_size != m88k_stack_size)
1819 warning ("Internal gcc error: stack size has changed by %d bytes",
1820 m88k_stack_size - old_stack_size);
1825 if (TARGET_OPTIMIZE_ARG_AREA
1827 && ! uses_arg_area_p ())
1829 /* The incoming argument area is used for stack space if it is not
1830 used (or if -mno-use-arg-area is given). */
1831 if ((m88k_stack_size -= REG_PARM_STACK_SPACE (0)) < 0)
1832 m88k_stack_size = 0;
1835 if (m88k_stack_size)
1836 output_reg_adjust (stream, 31, 31, -m88k_stack_size, 0);
1839 preserve_registers (stream, m88k_fp_offset + 4, 1);
1841 if (frame_pointer_needed)
1842 output_reg_adjust (stream, 30, 31, m88k_fp_offset, 0);
1844 if (TARGET_OCS_DEBUG_INFO)
1845 PUT_OCS_FUNCTION_START (stream);
1847 if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM])
1852 fprintf (stream, "\tor\t %s,%s,0\n",
1853 reg_names[TEMP_REGNUM], reg_names[1]);
1854 ASM_GENERATE_INTERNAL_LABEL (label, "Lab", m88k_function_number);
1855 fprintf (stream, "\tbsr.n\t %s\n", &label[1]);
1856 fprintf (stream, "\tor.u\t %s,%s,%shi16(%s#abdiff)\n",
1857 reg_names[PIC_OFFSET_TABLE_REGNUM], reg_names[0],
1858 m88k_pound_sign, &label[1]);
1859 ASM_OUTPUT_INTERNAL_LABEL (stream, "Lab", m88k_function_number);
1860 fprintf (stream, "\tor\t %s,%s,%slo16(%s#abdiff)\n",
1861 reg_names[PIC_OFFSET_TABLE_REGNUM],
1862 reg_names[PIC_OFFSET_TABLE_REGNUM],
1863 m88k_pound_sign, &label[1]);
1864 fprintf (stream, "\taddu\t %s,%s,%s\n",
1865 reg_names[PIC_OFFSET_TABLE_REGNUM],
1866 reg_names[PIC_OFFSET_TABLE_REGNUM], reg_names[1]);
1868 fprintf (stream, "\tor\t %s,%s,0\n",
1869 reg_names[1], reg_names[TEMP_REGNUM]);
1872 m88k_prologue_done = 1; /* it's ok now to put out ln directives */
1875 /* This function generates the assembly code for function exit,
1876 on machines that need it. Args are same as for FUNCTION_PROLOGUE.
1878 The function epilogue should not depend on the current stack pointer!
1879 It should use the frame pointer only, if there is a frame pointer.
1880 This is mandatory because of alloca; we also take advantage of it to
1881 omit stack adjustments before returning. */
1884 m88k_output_epilogue (stream, size)
1888 rtx insn = get_last_insn ();
1889 #if (MONITOR_GCC & 0x4) /* What are interesting prologue/epilogue values? */
1890 fprintf (stream, "; size = %d, m88k_fp_offset = %d, m88k_stack_size = %d\n",
1891 size, m88k_fp_offset, m88k_stack_size);
1894 output_short_branch_defs (stream);
1896 if (TARGET_OCS_DEBUG_INFO)
1897 PUT_OCS_FUNCTION_END (stream);
1899 /* If the last insn was a BARRIER, we don't have to write any code. */
1900 if (GET_CODE (insn) == NOTE)
1901 insn = prev_nonnote_insn (insn);
1902 if (insn && GET_CODE (insn) == BARRIER)
1904 if (current_function_epilogue_delay_list)
1909 if (frame_pointer_needed)
1910 output_reg_adjust (stream, 31, 30, -m88k_fp_offset, 0);
1913 preserve_registers (stream, m88k_fp_offset + 4, 0);
1915 output_reg_adjust (stream, 31, 31, m88k_stack_size, 1);
1918 fprintf (stream, "\n");
1920 if (TARGET_OCS_DEBUG_INFO)
1921 output_tdesc (stream, m88k_fp_offset + 4);
1923 m88k_function_number++;
1924 m88k_prologue_done = 0; /* don't put out ln directives */
1925 variable_args_p = 0; /* has variable args */
1928 /* Output code to STREAM to set DSTREG to SRCREG + AMOUNT. Issue
1929 a return instruction and use it's delay slot based on RETURN_P. */
1932 output_reg_adjust (stream, dstreg, srcreg, amount, return_p)
1934 int dstreg, srcreg, amount, return_p;
1947 if (amount == 0 && dstreg == srcreg)
1950 fprintf (stream, "\tjmp\t %s\n", reg_names[1]);
1953 else if (SMALL_INTVAL (amount))
1954 sprintf (incr, "\t%s\t %s,%s,%d", opname,
1955 reg_names[dstreg], reg_names[srcreg], amount);
1960 operands[0] = gen_rtx (REG, SImode, TEMP_REGNUM);
1961 operands[1] = gen_rtx (CONST_INT, VOIDmode, amount);
1962 output_asm_insn (output_load_const_int (SImode, operands),
1964 sprintf (incr, "\t%s\t %s,%s,%s", opname,
1965 reg_names[dstreg], reg_names[srcreg], reg_names[TEMP_REGNUM]);
1969 fprintf (stream, "%s\n", incr);
1970 else if (flag_delayed_branch)
1971 fprintf (stream, "\tjmp.n\t %s\n%s\n", reg_names[1], incr);
1973 fprintf (stream, "%s\n\tjmp\t %s\n", incr, reg_names[1]);
1976 /* Save/restore the preserve registers. base is the highest offset from
1977 r31 at which a register is stored. store_p is true if stores are to
1978 be done; otherwise loads. When loading, output the epilogue delay
1982 preserve_registers (stream, base, store_p)
1988 char *fmt = (store_p ? "\tst%s\t %s,%s,%d\n" : "\tld%s\t %s,%s,%d\n");
1993 } mem_op[FIRST_PSEUDO_REGISTER];
1994 struct mem_op *mo_ptr = mem_op;
1996 /* The 88open OCS mandates that preserved registers be stored in
1997 increasing order. For compatibility with current practice,
1998 the order is r1, r30, then the preserve registers. */
2003 /* An extra word is given in this case to make best use of double
2005 if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM])
2007 fprintf (stream, fmt, "", reg_names[1], reg_names[31], offset);
2012 /* Walk the registers to save recording all single memory operations. */
2013 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2014 if (save_regs[regno])
2016 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2019 mo_ptr->regno = regno;
2020 mo_ptr->offset = offset;
2031 /* Walk the registers to save recording all double memory operations.
2032 This avoids a delay in the epilogue (ld.d/ld). */
2034 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2035 if (save_regs[regno])
2037 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2044 mo_ptr->regno = regno-1;
2045 mo_ptr->offset = offset-4;
2053 /* Output the delay insns interleaved with the memory operations. */
2054 if (! store_p && current_function_epilogue_delay_list)
2056 rtx delay_insns = current_function_epilogue_delay_list;
2059 /* The first delay insn goes after the restore of r1. */
2062 final_scan_insn (XEXP (delay_insns, 0), stream, 1, 0, 1);
2063 delay_insns = XEXP (delay_insns, 1);
2068 /* Find a memory operation that doesn't conflict with this insn. */
2069 for (mo_ptr = mem_op; mo_ptr->regno != 0; mo_ptr++)
2073 rtx ok_insns = delay_insns;
2076 for (i = 0; i < mo_ptr->nregs; i++)
2077 epilogue_dead_regs[mo_ptr->regno + i] = 1;
2081 insn = XEXP (ok_insns, 0);
2082 ok_insns = XEXP (ok_insns, 1);
2084 if (! ok_for_epilogue_p (PATTERN (insn)))
2086 for (i = 0; i < mo_ptr->nregs; i++)
2087 epilogue_dead_regs[mo_ptr->regno + i] = 0;
2089 break; /* foreach delay insn */
2094 fprintf (stream, fmt, mo_ptr->nregs > 1 ? ".d" : "",
2095 reg_names[mo_ptr->regno], reg_names[31],
2098 break; /* foreach memory operation */
2102 final_scan_insn (XEXP (delay_insns, 0), stream, 1, 0, 1);
2103 delay_insns = XEXP (delay_insns, 1);
2107 /* Output the memory operations. */
2108 for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++)
2111 fprintf (stream, fmt, mo_ptr->nregs > 1 ? ".d" : "",
2112 reg_names[mo_ptr->regno], reg_names[31], mo_ptr->offset);
2116 /* Convert the address expression REG to a CFA offset. */
2119 m88k_debugger_offset (reg, offset)
2121 register int offset;
2123 if (GET_CODE (reg) == PLUS)
2125 offset = INTVAL (XEXP (reg, 1));
2126 reg = XEXP (reg, 0);
2129 /* Put the offset in terms of the CFA (arg pointer). */
2130 if (reg == frame_pointer_rtx)
2131 offset += m88k_fp_offset - m88k_stack_size;
2132 else if (reg == stack_pointer_rtx)
2133 offset -= m88k_stack_size;
2134 else if (reg != arg_pointer_rtx)
2136 #if (MONITOR_GCC & 0x10) /* Watch for suspicious symbolic locations. */
2137 if (! (GET_CODE (reg) == REG
2138 && REGNO (reg) >= FIRST_PSEUDO_REGISTER))
2139 warning ("Internal gcc error: Can't express symbolic location");
2147 /* Output the 88open OCS proscribed text description information.
2150 0 22: info-byte-length (16 bytes)
2151 0 2: info-alignment (word 2)
2152 1 32: info-protocol (version 1)
2153 2 32: starting-address (inclusive, not counting prologue)
2154 3 32: ending-address (exclusive, not counting epilog)
2155 4 8: info-variant (version 1)
2156 4 17: register-save-mask (from register 14 to 30)
2158 4 1: return-address-info-discriminant
2159 4 5: frame-address-register
2160 5 32: frame-address-offset
2161 6 32: return-address-info
2162 7 32: register-save-offset */
2165 output_tdesc (file, offset)
2170 long mask, return_address_info, register_save_offset;
2173 for (mask = 0, i = 0, regno = FIRST_OCS_PRESERVE_REGISTER;
2174 regno <= LAST_OCS_PRESERVE_REGISTER;
2178 if (save_regs[regno])
2187 if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM])
2189 return_address_info = - m88k_stack_size + offset;
2190 register_save_offset = return_address_info - i*4;
2194 return_address_info = 1;
2195 register_save_offset = - m88k_stack_size + offset + 4 - i*4;
2200 fprintf (file, "\t%s\t %d", INT_ASM_OP, (16 << 2) | 2 /* 8:0,22:16,2:2 */);
2201 fprintf (file, ",%d", flag_pic ? 2 : 1);
2203 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_START_PREFIX, m88k_function_number);
2204 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2205 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_END_PREFIX, m88k_function_number);
2206 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2208 fprintf (file, ",0x%x", /* 8:1,17:0x%.3x,1:0,1:%d,5:%d */
2211 ((!!save_regs[1]) << 5) |
2212 ((frame_pointer_needed
2213 ? FRAME_POINTER_REGNUM
2214 : STACK_POINTER_REGNUM)));
2216 fprintf (file, ",0x%x", (m88k_stack_size
2217 - (frame_pointer_needed ? m88k_fp_offset : 0)));
2218 fprintf (file, ",0x%x", return_address_info);
2219 fprintf (file, ",0x%x\n", register_save_offset);
2224 /* Output assembler code to FILE to increment profiler label # LABELNO
2225 for profiling a function entry. NAME is the mcount function name
2226 (varies), SAVEP indicates whether the parameter registers need to
2227 be saved and restored. */
2230 output_function_profiler (file, labelno, name, savep)
2238 char *temp = (savep ? reg_names[2] : reg_names[10]);
2242 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2243 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2244 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2245 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2246 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2249 ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno);
2252 fprintf (file, "\tor.u\t %s,%s,%shi16(%s#got_rel)\n",
2253 temp, reg_names[0], m88k_pound_sign, &label[1]);
2254 fprintf (file, "\tor\t %s,%s,%slo16(%s#got_rel)\n",
2255 temp, temp, m88k_pound_sign, &label[1]);
2256 sprintf (dbi, "\tld\t %s,%s,%s\n", temp,
2257 reg_names[PIC_OFFSET_TABLE_REGNUM], temp);
2261 sprintf (dbi, "\tld\t %s,%s,%s#got_rel\n", temp,
2262 reg_names[PIC_OFFSET_TABLE_REGNUM], &label[1]);
2266 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n",
2267 temp, reg_names[0], m88k_pound_sign, &label[1]);
2268 sprintf (dbi, "\tor\t %s,%s,%slo16(%s)\n",
2269 temp, temp, m88k_pound_sign, &label[1]);
2273 fprintf (file, "\tbsr.n\t %s#plt\n", name);
2275 fprintf (file, "\tbsr.n\t %s\n", name);
2280 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2281 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2282 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2283 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2284 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2288 /* Output assembler code to FILE to initialize basic-block profiling for
2289 the current module. LABELNO is unique to each instance. */
2292 output_function_block_profiler (file, labelno)
2299 ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 0);
2300 ASM_GENERATE_INTERNAL_LABEL (label, "LPY", labelno);
2302 /* @@ Need to deal with PIC. I'm not sure what the requirements are on
2303 register usage, so I used r26/r27 to be safe. */
2304 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n", reg_names[27], reg_names[0],
2305 m88k_pound_sign, &block[1]);
2306 fprintf (file, "\tld\t %s,%s,%slo16(%s)\n", reg_names[26], reg_names[27],
2307 m88k_pound_sign, &block[1]);
2308 fprintf (file, "\tbcnd\t %sne0,%s,%s\n",
2309 m88k_pound_sign, reg_names[26], &label[1]);
2310 fputs ("\tbsr.n\t ", file);
2311 ASM_OUTPUT_LABELREF (file, "__bb_init_func");
2313 fprintf (file, "\tor\t %s,%s,%slo16(%s)\n", reg_names[2], reg_names[27],
2314 m88k_pound_sign, &block[1]);
2315 ASM_OUTPUT_INTERNAL_LABEL (file, "LPY", labelno);
2318 /* Output assembler code to FILE to increment the count associated with
2319 the basic block number BLOCKNO. */
2322 output_block_profiler (file, blockno)
2328 ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 0);
2330 /* @@ Need to deal with PIC. I'm not sure what the requirements are on
2331 register usage, so I used r26/r27 to be safe. */
2332 fprintf (file, "\tor.u\t %s,%s,%shi16(%s+%d)\n", reg_names[27], reg_names[0],
2333 m88k_pound_sign, &block[1], 4 * blockno);
2334 fprintf (file, "\tld\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27],
2335 m88k_pound_sign, &block[1], 4 * blockno);
2336 fprintf (file, "\taddu\t %s,%s,1\n", reg_names[26], reg_names[26]);
2337 fprintf (file, "\tst\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27],
2338 m88k_pound_sign, &block[1], 4 * blockno);
2341 /* Determine whether a function argument is passed in a register, and
2344 The arguments are CUM, which summarizes all the previous
2345 arguments; MODE, the machine mode of the argument; TYPE,
2346 the data type of the argument as a tree node or 0 if that is not known
2347 (which happens for C support library functions); and NAMED,
2348 which is 1 for an ordinary argument and 0 for nameless arguments that
2349 correspond to `...' in the called function's prototype.
2351 The value of the expression should either be a `reg' RTX for the
2352 hard register in which to pass the argument, or zero to pass the
2353 argument on the stack.
2355 On the m88000 the first eight words of args are normally in registers
2356 and the rest are pushed. Double precision floating point must be
2357 double word aligned (and if in a register, starting on an even
2358 register). Structures and unions which are not 4 byte, and word
2359 aligned are passed in memory rather than registers, even if they
2360 would fit completely in the registers under OCS rules.
2362 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2363 For structures that are passed in memory, but could have been
2364 passed in registers, we first load the structure into the
2365 register, and then when the last argument is passed, we store
2366 the registers into the stack locations. This fixes some bugs
2367 where GCC did not expect to have register arguments, followed
2368 by stack arguments, followed by register arguments. */
2371 m88k_function_arg (args_so_far, mode, type, named)
2372 CUMULATIVE_ARGS args_so_far;
2373 enum machine_mode mode;
2379 if (type != 0 /* undo putting struct in register */
2380 && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
2383 if (mode == BLKmode && TARGET_WARN_PASS_STRUCT)
2384 warning ("argument #%d is a structure", args_so_far + 1);
2386 if ((args_so_far & 1) != 0
2387 && (mode == DImode || mode == DFmode
2388 || (type != 0 && TYPE_ALIGN (type) > 32)))
2393 return (rtx) 0; /* don't put args in registers */
2396 if (type == 0 && mode == BLKmode)
2397 abort (); /* m88k_function_arg argument `type' is NULL for BLKmode. */
2399 bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
2400 words = (bytes + 3) / 4;
2402 if (args_so_far + words > 8)
2403 return (rtx) 0; /* args have exhausted registers */
2405 else if (mode == BLKmode
2406 && (TYPE_ALIGN (type) != BITS_PER_WORD
2407 || bytes != UNITS_PER_WORD))
2410 return gen_rtx (REG,
2411 ((mode == BLKmode) ? TYPE_MODE (type) : mode),
2415 /* Do what is necessary for `va_start'. The argument is ignored;
2416 We look at the current function to determine if stdargs or varargs
2417 is used and fill in an initial va_list. A pointer to this constructor
2421 m88k_builtin_saveregs (arglist)
2424 rtx block, addr, argsize;
2425 tree fntype = TREE_TYPE (current_function_decl);
2426 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2427 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2428 != void_type_node)))
2429 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
2431 variable_args_p = 1;
2433 if (CONSTANT_P (current_function_arg_offset_rtx))
2435 fixed = (XINT (current_function_arg_offset_rtx, 0)
2436 + argadj) / UNITS_PER_WORD;
2437 argsize = gen_rtx (CONST_INT, VOIDmode, fixed);
2442 argsize = plus_constant (current_function_arg_offset_rtx, argadj);
2443 argsize = expand_shift (RSHIFT_EXPR, Pmode, argsize,
2444 build_int_2 (2, 0), argsize, 0);
2447 /* Allocate the va_list constructor */
2448 block = assign_stack_local (BLKmode, 3 * UNITS_PER_WORD, BITS_PER_WORD);
2449 RTX_UNCHANGING_P (block) = 1;
2450 RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
2452 /* Store the argsize as the __va_arg member. */
2453 emit_move_insn (change_address (block, SImode, XEXP (block, 0)),
2456 /* Store the arg pointer in the __va_stk member. */
2457 emit_move_insn (change_address (block, Pmode,
2458 plus_constant (XEXP (block, 0),
2460 copy_to_reg (virtual_incoming_args_rtx));
2462 /* Allocate the register space, and store it as the __va_reg member. */
2463 addr = assign_stack_local (BLKmode, 8 * UNITS_PER_WORD, -1);
2464 MEM_IN_STRUCT_P (addr) = 1;
2465 RTX_UNCHANGING_P (addr) = 1;
2466 RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
2467 emit_move_insn (change_address (block, Pmode,
2468 plus_constant (XEXP (block, 0),
2469 2 * UNITS_PER_WORD)),
2470 copy_to_reg (XEXP (addr, 0)));
2472 /* Now store the incoming registers and return the address of the
2473 va_list constructor. */
2477 change_address (addr, Pmode,
2478 plus_constant (XEXP (addr, 0),
2479 fixed * UNITS_PER_WORD)),
2482 return copy_to_reg (XEXP (block, 0));
2485 /* If cmpsi has not been generated, emit code to do the test. Return the
2486 expression describing the test of operator OP. */
2489 emit_test (op, mode)
2491 enum machine_mode mode;
2493 if (m88k_compare_reg == 0)
2494 emit_insn (gen_test (m88k_compare_op0, m88k_compare_op1));
2495 return (gen_rtx (op, mode, m88k_compare_reg, const0_rtx));
2498 /* Determine how to best perform cmpsi/bxx, where cmpsi has a constant
2499 operand. All tests with zero (albeit swapped) and all equality tests
2500 with a constant are done with bcnd. The remaining cases are swapped
2504 emit_bcnd (op, label)
2508 if (m88k_compare_op1 == const0_rtx)
2509 emit_jump_insn (optimize
2510 ? gen_bxx (emit_test (op, VOIDmode), label)
2511 : gen_bcnd (gen_rtx (op, VOIDmode,
2512 m88k_compare_op0, const0_rtx),
2514 else if (m88k_compare_op0 == const0_rtx)
2515 emit_jump_insn (optimize
2516 ? gen_bxx (emit_test (op, VOIDmode), label)
2517 : gen_bcnd (gen_rtx (swap_condition (op), VOIDmode,
2518 m88k_compare_op1, const0_rtx),
2520 else if (op != EQ && op != NE)
2521 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2524 rtx zero = gen_reg_rtx (SImode);
2528 if (GET_CODE (m88k_compare_op1) == CONST_INT)
2530 reg = force_reg (SImode, m88k_compare_op0);
2531 constant = m88k_compare_op1;
2535 reg = force_reg (SImode, m88k_compare_op1);
2536 constant = m88k_compare_op0;
2538 value = INTVAL (constant);
2540 /* Perform an arithmetic computation to make the compared-to value
2541 zero, but avoid loosing if the bcnd is later changed into sxx. */
2542 if (SMALL_INTVAL (value))
2543 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2546 if (SMALL_INTVAL (-value))
2547 emit_insn (gen_addsi3 (zero, reg,
2548 gen_rtx (CONST_INT, VOIDmode, -value)));
2550 emit_insn (gen_xorsi3 (zero, reg, constant));
2552 emit_jump_insn (gen_bcnd (gen_rtx (op, VOIDmode,
2559 /* Print an operand. Recognize special options, documented below. */
2562 print_operand (file, x, code)
2567 enum rtx_code xc = (x ? GET_CODE (x) : UNKNOWN);
2568 register int value = (xc == CONST_INT ? INTVAL (x) : 0);
2569 static int sequencep;
2570 static int reversep;
2574 if (code < 'B' || code > 'E')
2575 output_operand_lossage ("%R not followed by %B/C/D/E");
2577 xc = reverse_condition (xc);
2583 case '*': /* addressing base register for PIC */
2584 fputs (reg_names[PIC_OFFSET_TABLE_REGNUM], file); return;
2586 case '#': /* SVR4 pound-sign syntax character (empty if SVR3) */
2587 fputs (m88k_pound_sign, file); return;
2589 case 'X': /* print the upper 16 bits... */
2591 case 'x': /* print the lower 16 bits of the integer constant in hex */
2592 if (xc != CONST_INT)
2593 output_operand_lossage ("invalid %x/X value");
2594 fprintf (file, "0x%x", value & 0xffff); return;
2596 case 'H': /* print the low 16 bits of the negated integer constant */
2597 if (xc != CONST_INT)
2598 output_operand_lossage ("invalid %H value");
2600 case 'h': /* print the register or low 16 bits of the integer constant */
2603 if (xc != CONST_INT)
2604 output_operand_lossage ("invalid %h value");
2605 fprintf (file, "%d", value & 0xffff);
2608 case 'Q': /* print the low 8 bits of the negated integer constant */
2609 if (xc != CONST_INT)
2610 output_operand_lossage ("invalid %Q value");
2612 case 'q': /* print the register or low 8 bits of the integer constant */
2615 if (xc != CONST_INT)
2616 output_operand_lossage ("invalid %q value");
2617 fprintf (file, "%d", value & 0xff);
2620 case 'w': /* print the integer constant (X == 32 ? 0 : 32 - X) */
2621 if (xc != CONST_INT)
2622 output_operand_lossage ("invalid %o value");
2623 fprintf (file, "%d", value == 32 ? 0 : 32 - value);
2626 case 'p': /* print the logarithm of the integer constant */
2628 || (value = exact_log2 (value)) < 0)
2629 output_operand_lossage ("invalid %p value");
2630 fprintf (file, "%d", value);
2633 case 'S': /* compliment the value and then... */
2635 case 's': /* print the width and offset values forming the integer
2636 constant with a SET instruction. See integer_ok_for_set. */
2638 register unsigned mask, uval = value;
2639 register int top, bottom;
2641 if (xc != CONST_INT)
2642 output_operand_lossage ("invalid %s/S value");
2643 /* All the "one" bits must be contiguous. If so, MASK will be
2644 a power of two or zero. */
2645 mask = (uval | (uval - 1)) + 1;
2646 if (!(uval && POWER_OF_2_or_0 (mask)))
2647 output_operand_lossage ("invalid %s/S value");
2648 top = mask ? exact_log2 (mask) : 32;
2649 bottom = exact_log2 (uval & ~(uval - 1));
2650 fprintf (file,"%d<%d>", top - bottom, bottom);
2654 case 'P': /* print nothing if pc_rtx; output label_ref */
2655 if (xc == LABEL_REF)
2656 output_addr_const (file, x);
2658 output_operand_lossage ("invalid %P operand");
2661 case 'L': /* print 0 or 1 if operand is label_ref and then... */
2662 fputc (xc == LABEL_REF ? '1' : '0', file);
2663 case '.': /* print .n if delay slot is used */
2664 fputs ((final_sequence
2665 && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
2666 ? ".n\t" : "\t", file);
2669 case 'R': /* reverse the condition of the next print_operand
2670 if operand is a label_ref. */
2672 reversep = (xc == LABEL_REF);
2675 case 'B': /* bcnd branch values */
2676 fputs (m88k_pound_sign, file);
2679 case EQ: fputs ("eq0", file); return;
2680 case NE: fputs ("ne0", file); return;
2681 case GT: fputs ("gt0", file); return;
2682 case LE: fputs ("le0", file); return;
2683 case LT: fputs ("lt0", file); return;
2684 case GE: fputs ("ge0", file); return;
2685 default: output_operand_lossage ("invalid %B value");
2688 case 'C': /* bb0/bb1 branch values for comparisons */
2689 fputs (m88k_pound_sign, file);
2692 case EQ: fputs ("eq", file); return;
2693 case NE: fputs ("ne", file); return;
2694 case GT: fputs ("gt", file); return;
2695 case LE: fputs ("le", file); return;
2696 case LT: fputs ("lt", file); return;
2697 case GE: fputs ("ge", file); return;
2698 case GTU: fputs ("hi", file); return;
2699 case LEU: fputs ("ls", file); return;
2700 case LTU: fputs ("lo", file); return;
2701 case GEU: fputs ("hs", file); return;
2702 default: output_operand_lossage ("invalid %C value");
2705 case 'D': /* bcnd branch values for float comparisons */
2708 case EQ: fputs ("0xa", file); return;
2709 case NE: fputs ("0x5", file); return;
2710 case GT: fputs (m88k_pound_sign, file);
2711 fputs ("gt0", file); return;
2712 case LE: fputs ("0xe", file); return;
2713 case LT: fputs ("0x4", file); return;
2714 case GE: fputs ("0xb", file); return;
2715 default: output_operand_lossage ("invalid %D value");
2718 case 'E': /* bcnd branch values for special integers */
2721 case EQ: fputs ("0x8", file); return;
2722 case NE: fputs ("0x7", file); return;
2723 default: output_operand_lossage ("invalid %E value");
2726 case 'd': /* second register of a two register pair */
2728 output_operand_lossage ("`%d' operand isn't a register");
2729 fputs (reg_names[REGNO (x) + 1], file);
2732 case 'r': /* an immediate 0 should be represented as `r0' */
2733 if (x == const0_rtx)
2735 fputs (reg_names[0], file);
2739 output_operand_lossage ("invalid %r value");
2745 if (REGNO (x) == ARG_POINTER_REGNUM)
2746 output_operand_lossage ("operand is r0");
2748 fputs (reg_names[REGNO (x)], file);
2750 else if (xc == PLUS)
2753 output_address (XEXP (x, 0));
2754 else if (xc == CONST_DOUBLE)
2755 output_operand_lossage ("operand is const_double");
2757 output_addr_const (file, x);
2760 case 'g': /* append #got_rel as needed */
2761 if (flag_pic && (xc == SYMBOL_REF || xc == LABEL_REF))
2763 output_addr_const (file, x);
2764 fputs ("#got_rel", file);
2769 case 'a': /* (standard), assume operand is an address */
2770 case 'c': /* (standard), assume operand is an immediate value */
2771 case 'l': /* (standard), assume operand is a label_ref */
2772 case 'n': /* (standard), like %c, except negate first */
2774 output_operand_lossage ("invalid code");
2779 print_operand_address (file, addr)
2783 register rtx reg0, reg1, temp;
2785 switch (GET_CODE (addr))
2788 if (REGNO (addr) == ARG_POINTER_REGNUM)
2791 fprintf (file, "%s,%s", reg_names[0], reg_names [REGNO (addr)]);
2795 fprintf (file, "%s,%slo16(",
2796 reg_names[REGNO (XEXP (addr, 0))], m88k_pound_sign);
2797 output_addr_const (file, XEXP (addr, 1));
2802 reg0 = XEXP (addr, 0);
2803 reg1 = XEXP (addr, 1);
2804 if (GET_CODE (reg0) == MULT || GET_CODE (reg0) == CONST_INT)
2811 if ((REG_P (reg0) && REGNO (reg0) == ARG_POINTER_REGNUM)
2812 || (REG_P (reg1) && REGNO (reg1) == ARG_POINTER_REGNUM))
2815 else if (REG_P (reg0))
2818 fprintf (file, "%s,%s",
2819 reg_names [REGNO (reg0)], reg_names [REGNO (reg1)]);
2821 else if (GET_CODE (reg1) == CONST_INT)
2822 fprintf (file, "%s,%d",
2823 reg_names [REGNO (reg0)], INTVAL (reg1));
2825 else if (GET_CODE (reg1) == MULT)
2827 rtx mreg = XEXP (reg1, 0);
2828 if (REGNO (mreg) == ARG_POINTER_REGNUM)
2831 fprintf (file, "%s[%s]", reg_names[REGNO (reg0)],
2832 reg_names[REGNO (mreg)]);
2835 else if (GET_CODE (reg1) == ZERO_EXTRACT)
2837 fprintf (file, "%s,%slo16(",
2838 reg_names[REGNO (reg0)], m88k_pound_sign);
2839 output_addr_const (file, XEXP (reg1, 0));
2845 fprintf (file, "%s,", reg_names[REGNO (reg0)]);
2846 output_addr_const (file, reg1);
2847 fputs ("#got_rel", file);
2857 if (REGNO (XEXP (addr, 0)) == ARG_POINTER_REGNUM)
2860 fprintf (file, "%s[%s]",
2861 reg_names[0], reg_names[REGNO (XEXP (addr, 0))]);
2865 fprintf (file, "%s,%shi16(", reg_names[0], m88k_pound_sign);
2866 output_addr_const (file, XEXP (addr, 0));
2871 fprintf (file, "%s,%d", reg_names[0], INTVAL (addr));
2875 fprintf (file, "%s,", reg_names[0]);
2876 if (SHORT_ADDRESS_P (addr, temp))
2878 fprintf (file, "%siw16(", m88k_pound_sign);
2879 output_addr_const (file, addr);
2883 output_addr_const (file, addr);