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 Version 2 port by Tom Wood (twood@pets.sps.mot.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>
32 #include "hard-reg-set.h"
34 #include "insn-config.h"
35 #include "conditions.h"
36 #include "insn-flags.h"
38 #include "insn-attr.h"
44 extern char *version_string;
45 extern time_t time ();
46 extern char *ctime ();
47 extern int flag_traditional;
48 extern FILE *asm_out_file;
50 static char out_rcs_id[] = "$What: <@(#) m88k.c,v 1.8> $";
51 static char tm_rcs_id [] = TM_RCS_ID;
53 char *m88k_pound_sign = ""; /* Either # for SVR4 or empty for SVR3 */
54 char *m88k_short_data;
56 char m88k_volatile_code;
58 unsigned m88k_gp_threshold = 0;
59 int m88k_prologue_done = 0; /* Ln directives can now be emitted */
60 int m88k_function_number = 0; /* Counter unique to each function */
61 int m88k_fp_offset = 0; /* offset of frame pointer if used */
62 int m88k_stack_size = 0; /* size of allocated stack (including frame) */
65 rtx m88k_compare_reg; /* cmp output pseudo register */
66 rtx m88k_compare_op0; /* cmpsi operand 0 */
67 rtx m88k_compare_op1; /* cmpsi operand 1 */
69 enum processor_type m88k_cpu; /* target cpu */
71 /* Determine what instructions are needed to manufacture the integer VALUE
75 classify_integer (mode, value)
76 enum machine_mode mode;
83 else if (SMALL_INTVAL (value))
85 else if (SMALL_INTVAL (-value))
87 else if (mode == HImode)
89 else if (mode == QImode)
91 else if ((value & 0xffff) == 0)
93 else if (integer_ok_for_set (value))
99 /* Return the bit number in a compare word corresponding to CONDITION. */
102 condition_value (condition)
105 switch (GET_CODE (condition))
122 integer_ok_for_set (value)
123 register unsigned value;
125 /* All the "one" bits must be contiguous. If so, MASK + 1 will be
126 a power of two or zero. */
127 register unsigned mask = (value | (value - 1));
128 return (value && POWER_OF_2_or_0 (mask + 1));
132 output_load_const_int (mode, operands)
133 enum machine_mode mode;
136 static char *patterns[] =
144 "or.u %0,%#r0,%X1\n\tor %0,%0,%x1",
147 if (! REG_P (operands[0])
148 || GET_CODE (operands[1]) != CONST_INT)
150 return patterns[classify_integer (mode, INTVAL (operands[1]))];
153 /* These next two routines assume that floating point numbers are represented
154 in a manner which is consistent between host and target machines. */
157 output_load_const_float (operands)
160 /* These can return 0 under some circumstances when cross-compiling. */
161 operands[0] = operand_subword (operands[0], 0, 0, SFmode);
162 operands[1] = operand_subword (operands[1], 0, 0, SFmode);
164 return output_load_const_int (SImode, operands);
168 output_load_const_double (operands)
173 /* These can return zero on some cross-compilers, but there's nothing
174 we can do about it. */
175 latehalf[0] = operand_subword (operands[0], 1, 0, DFmode);
176 latehalf[1] = operand_subword (operands[1], 1, 0, DFmode);
178 operands[0] = operand_subword (operands[0], 0, 0, DFmode);
179 operands[1] = operand_subword (operands[1], 0, 0, DFmode);
181 output_asm_insn (output_load_const_int (SImode, operands), operands);
183 operands[0] = latehalf[0];
184 operands[1] = latehalf[1];
186 return output_load_const_int (SImode, operands);
190 output_load_const_dimode (operands)
195 latehalf[0] = operand_subword (operands[0], 1, 0, DImode);
196 latehalf[1] = operand_subword (operands[1], 1, 0, DImode);
198 operands[0] = operand_subword (operands[0], 0, 0, DImode);
199 operands[1] = operand_subword (operands[1], 0, 0, DImode);
201 output_asm_insn (output_load_const_int (SImode, operands), operands);
203 operands[0] = latehalf[0];
204 operands[1] = latehalf[1];
206 return output_load_const_int (SImode, operands);
209 /* Emit insns to move operands[1] into operands[0].
211 Return 1 if we have written out everything that needs to be done to
212 do the move. Otherwise, return 0 and the caller will emit the move
215 SCRATCH if non zero can be used as a scratch register for the move
216 operation. It is provided by a SECONDARY_RELOAD_* macro if needed. */
219 emit_move_sequence (operands, mode, scratch)
221 enum machine_mode mode;
224 register rtx operand0 = operands[0];
225 register rtx operand1 = operands[1];
227 /* Handle most common case first: storing into a register. */
228 if (register_operand (operand0, mode))
230 if (register_operand (operand1, mode)
231 || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
232 || GET_CODE (operand1) == HIGH
233 /* Only `general_operands' can come here, so MEM is ok. */
234 || GET_CODE (operand1) == MEM)
236 /* Run this case quickly. */
237 emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
241 else if (GET_CODE (operand0) == MEM)
243 if (register_operand (operand1, mode)
244 || (operand1 == const0_rtx && GET_MODE_SIZE (mode) <= UNITS_PER_WORD))
246 /* Run this case quickly. */
247 emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
250 if (! reload_in_progress && ! reload_completed)
252 operands[0] = validize_mem (operand0);
253 operands[1] = operand1 = force_reg (mode, operand1);
257 /* Simplify the source if we need to. */
258 if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
260 if (GET_CODE (operand1) != CONST_INT
261 && GET_CODE (operand1) != CONST_DOUBLE)
263 rtx temp = ((reload_in_progress || reload_completed)
265 operands[1] = legitimize_address (flag_pic
266 && symbolic_address_p (operand1),
267 operand1, temp, scratch);
269 operands[1] = gen_rtx (SUBREG, mode, operands[1], 0);
273 /* Now have insn-emit do whatever it normally does. */
277 /* Return a legitimate reference for ORIG (either an address or a MEM)
278 using the register REG. If PIC and the address is already
279 position-independent, use ORIG. Newly generated position-independent
280 addresses go into a reg. This is REG if non zero, otherwise we
281 allocate register(s) as necessary. If this is called during reload,
282 and we need a second temp register, then we use SCRATCH, which is
283 provided via the SECONDARY_INPUT_RELOAD_CLASS mechanism. */
286 legitimize_address (pic, orig, reg, scratch)
292 rtx addr = (GET_CODE (orig) == MEM ? XEXP (orig, 0) : orig);
298 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
302 if (reload_in_progress || reload_completed)
305 reg = gen_reg_rtx (Pmode);
310 /* If not during reload, allocate another temp reg here for
311 loading in the address, so that these instructions can be
312 optimized properly. */
313 temp = ((reload_in_progress || reload_completed)
314 ? reg : gen_reg_rtx (Pmode));
316 emit_insn (gen_rtx (SET, VOIDmode, temp,
317 gen_rtx (HIGH, SImode,
318 gen_rtx (UNSPEC, SImode,
321 emit_insn (gen_rtx (SET, VOIDmode, temp,
322 gen_rtx (LO_SUM, SImode, temp,
323 gen_rtx (UNSPEC, SImode,
328 new = gen_rtx (MEM, Pmode,
329 gen_rtx (PLUS, SImode,
330 pic_offset_table_rtx, addr));
331 current_function_uses_pic_offset_table = 1;
332 RTX_UNCHANGING_P (new) = 1;
333 insn = emit_move_insn (reg, new);
334 /* Put a REG_EQUAL note on this insn, so that it can be optimized
336 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, orig,
340 else if (GET_CODE (addr) == CONST)
344 if (GET_CODE (XEXP (addr, 0)) == PLUS
345 && XEXP (XEXP (addr, 0), 0) == pic_offset_table_rtx)
350 if (reload_in_progress || reload_completed)
353 reg = gen_reg_rtx (Pmode);
356 if (GET_CODE (XEXP (addr, 0)) != PLUS) abort ();
358 base = legitimize_address (1, XEXP (XEXP (addr, 0), 0), reg, 0);
359 addr = legitimize_address (1, XEXP (XEXP (addr, 0), 1),
360 base == reg ? 0 : reg, 0);
362 if (GET_CODE (addr) == CONST_INT)
365 return plus_constant_for_output (base, INTVAL (addr));
366 else if (! reload_in_progress && ! reload_completed)
367 addr = force_reg (Pmode, addr);
368 /* We can't create any new registers during reload, so use the
369 SCRATCH reg provided by the reload_insi pattern. */
372 emit_move_insn (scratch, addr);
376 /* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS
377 macro needs to be adjusted so that a scratch reg is provided
381 new = gen_rtx (PLUS, SImode, base, addr);
382 /* Should we set special REG_NOTEs here? */
385 else if (! SHORT_ADDRESS_P (addr, temp))
389 if (reload_in_progress || reload_completed)
392 reg = gen_reg_rtx (Pmode);
395 emit_insn (gen_rtx (SET, VOIDmode,
396 reg, gen_rtx (HIGH, SImode, addr)));
397 new = gen_rtx (LO_SUM, SImode, reg, addr);
401 && GET_CODE (orig) == MEM)
403 new = gen_rtx (MEM, GET_MODE (orig), new);
404 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (orig);
405 MEM_VOLATILE_P (new) = MEM_VOLATILE_P (orig);
406 MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (orig);
411 /* Support functions for code to emit a block move. There are four methods
412 used to perform the block move:
414 + call the looping library function, e.g. __movstrSI64n8
415 + call a non-looping library function, e.g. __movstrHI15x11
416 + produce an inline sequence of ld/st instructions
418 The parameters below describe the library functions produced by
421 #define MOVSTR_LOOP 64 /* __movstrSI64n68 .. __movstrSI64n8 */
422 #define MOVSTR_QI 16 /* __movstrQI16x16 .. __movstrQI16x2 */
423 #define MOVSTR_HI 48 /* __movstrHI48x48 .. __movstrHI48x4 */
424 #define MOVSTR_SI 96 /* __movstrSI96x96 .. __movstrSI96x8 */
425 #define MOVSTR_DI 96 /* __movstrDI96x96 .. __movstrDI96x16 */
426 #define MOVSTR_ODD_HI 16 /* __movstrHI15x15 .. __movstrHI15x5 */
427 #define MOVSTR_ODD_SI 48 /* __movstrSI47x47 .. __movstrSI47x11,
428 __movstrSI46x46 .. __movstrSI46x10,
429 __movstrSI45x45 .. __movstrSI45x9 */
430 #define MOVSTR_ODD_DI 48 /* __movstrDI47x47 .. __movstrDI47x23,
431 __movstrDI46x46 .. __movstrDI46x22,
432 __movstrDI45x45 .. __movstrDI45x21,
433 __movstrDI44x44 .. __movstrDI44x20,
434 __movstrDI43x43 .. __movstrDI43x19,
435 __movstrDI42x42 .. __movstrDI42x18,
436 __movstrDI41x41 .. __movstrDI41x17 */
438 /* Limits for using the non-looping movstr functions. For the m88100
439 processor, we assume the source and destination are word aligned.
440 The QImode and HImode limits are the break even points where memcpy
441 does just as well and beyond which memcpy does better. For the
442 m88110, we tend to assume double word alignment, but also analyze
443 the word aligned cases. The analysis is complicated because memcpy
444 may use the cache control instructions for better performance. */
446 #define MOVSTR_QI_LIMIT_88100 13
447 #define MOVSTR_HI_LIMIT_88100 38
448 #define MOVSTR_SI_LIMIT_88100 MOVSTR_SI
449 #define MOVSTR_DI_LIMIT_88100 MOVSTR_SI
451 #define MOVSTR_QI_LIMIT_88000 16
452 #define MOVSTR_HI_LIMIT_88000 38
453 #define MOVSTR_SI_LIMIT_88000 72
454 #define MOVSTR_DI_LIMIT_88000 72
456 #define MOVSTR_QI_LIMIT_88110 16
457 #define MOVSTR_HI_LIMIT_88110 38
458 #define MOVSTR_SI_LIMIT_88110 72
459 #define MOVSTR_DI_LIMIT_88110 72
461 static enum machine_mode mode_from_align[] =
462 {VOIDmode, QImode, HImode, VOIDmode, SImode,
463 VOIDmode, VOIDmode, VOIDmode, DImode};
464 static int max_from_align[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI,
466 static int all_from_align[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0, MOVSTR_ODD_SI,
467 0, 0, 0, MOVSTR_ODD_DI};
469 static int best_from_align[3][9] =
470 {0, MOVSTR_QI_LIMIT_88100, MOVSTR_HI_LIMIT_88100, 0, MOVSTR_SI_LIMIT_88100,
471 0, 0, 0, MOVSTR_DI_LIMIT_88100,
472 0, MOVSTR_QI_LIMIT_88110, MOVSTR_HI_LIMIT_88110, 0, MOVSTR_SI_LIMIT_88110,
473 0, 0, 0, MOVSTR_DI_LIMIT_88110,
474 0, MOVSTR_QI_LIMIT_88000, MOVSTR_HI_LIMIT_88000, 0, MOVSTR_SI_LIMIT_88000,
475 0, 0, 0, MOVSTR_DI_LIMIT_88000};
477 static void block_move_loop ();
478 static void block_move_no_loop ();
479 static void block_move_sequence ();
481 /* Emit code to perform a block move. Choose the best method.
483 OPERANDS[0] is the destination.
484 OPERANDS[1] is the source.
485 OPERANDS[2] is the size.
486 OPERANDS[3] is the alignment safe to use. */
489 expand_block_move (dest_mem, src_mem, operands)
494 int align = INTVAL (operands[3]);
495 int constp = (GET_CODE (operands[2]) == CONST_INT);
496 int bytes = (constp ? INTVAL (operands[2]) : 0);
497 int target = (int) m88k_cpu;
499 assert (PROCESSOR_M88100 == 0);
500 assert (PROCESSOR_M88110 == 1);
501 assert (PROCESSOR_M88000 == 2);
503 if (constp && bytes <= 0)
506 /* Determine machine mode to do move with. */
507 if (align > 4 && !TARGET_88110)
509 else if (align <= 0 || align == 3)
510 abort (); /* block move invalid alignment. */
512 if (constp && bytes <= 3 * align)
513 block_move_sequence (operands[0], dest_mem, operands[1], src_mem,
516 else if (constp && bytes <= best_from_align[target][align])
517 block_move_no_loop (operands[0], dest_mem, operands[1], src_mem,
520 else if (constp && align == 4 && TARGET_88100)
521 block_move_loop (operands[0], dest_mem, operands[1], src_mem,
526 #ifdef TARGET_MEM_FUNCTIONS
527 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"), 0,
531 operands[2], SImode);
533 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcopy"), 0,
537 operands[2], SImode);
542 /* Emit code to perform a block move by calling a looping movstr library
543 function. SIZE and ALIGN are known constants. DEST and SRC are
547 block_move_loop (dest, dest_mem, src, src_mem, size, align)
553 enum machine_mode mode;
562 /* Determine machine mode to do move with. */
566 /* Determine the structure of the loop. */
567 count = size / MOVSTR_LOOP;
568 units = (size - count * MOVSTR_LOOP) / align;
573 units += MOVSTR_LOOP / align;
578 block_move_no_loop (dest, dest_mem, src, src_mem, size, align);
582 remainder = size - count * MOVSTR_LOOP - units * align;
584 mode = mode_from_align[align];
585 sprintf (entry, "__movstr%s%dn%d",
586 GET_MODE_NAME (mode), MOVSTR_LOOP, units * align);
587 entry_name = get_identifier (entry);
589 offset_rtx = gen_rtx (CONST_INT, VOIDmode,
590 MOVSTR_LOOP + (1 - units) * align);
592 value_rtx = gen_rtx (MEM, MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode,
593 gen_rtx (PLUS, Pmode,
594 gen_rtx (REG, Pmode, 3),
596 RTX_UNCHANGING_P (value_rtx) = RTX_UNCHANGING_P (src_mem);
597 MEM_VOLATILE_P (value_rtx) = MEM_VOLATILE_P (src_mem);
598 MEM_IN_STRUCT_P (value_rtx) = MEM_IN_STRUCT_P (src_mem);
600 emit_insn (gen_call_movstrsi_loop
601 (gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)),
602 dest, src, offset_rtx, value_rtx,
603 gen_rtx (REG, mode, ((units & 1) ? 4 : 5)),
604 gen_rtx (CONST_INT, VOIDmode, count)));
607 block_move_sequence (gen_rtx (REG, Pmode, 2), dest_mem,
608 gen_rtx (REG, Pmode, 3), src_mem,
609 remainder, align, MOVSTR_LOOP + align);
612 /* Emit code to perform a block move by calling a non-looping library
613 function. SIZE and ALIGN are known constants. DEST and SRC are
614 registers. OFFSET is the known starting point for the output pattern. */
617 block_move_no_loop (dest, dest_mem, src, src_mem, size, align)
623 enum machine_mode mode = mode_from_align[align];
624 int units = size / align;
625 int remainder = size - units * align;
633 if (remainder && size <= all_from_align[align])
635 most = all_from_align[align] - (align - remainder);
640 most = max_from_align[align];
643 sprintf (entry, "__movstr%s%dx%d",
644 GET_MODE_NAME (mode), most, size - remainder);
645 entry_name = get_identifier (entry);
647 offset_rtx = gen_rtx (CONST_INT, VOIDmode, most - (size - remainder));
649 value_rtx = gen_rtx (MEM, MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode,
650 gen_rtx (PLUS, Pmode,
651 gen_rtx (REG, Pmode, 3),
653 RTX_UNCHANGING_P (value_rtx) = RTX_UNCHANGING_P (src_mem);
654 MEM_VOLATILE_P (value_rtx) = MEM_VOLATILE_P (src_mem);
655 MEM_IN_STRUCT_P (value_rtx) = MEM_IN_STRUCT_P (src_mem);
657 value_reg = ((((most - (size - remainder)) / align) & 1) == 0
658 ? (align == 8 ? 6 : 5) : 4);
660 emit_insn (gen_call_block_move
661 (gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)),
662 dest, src, offset_rtx, value_rtx,
663 gen_rtx (REG, mode, value_reg)));
666 block_move_sequence (gen_rtx (REG, Pmode, 2), dest_mem,
667 gen_rtx (REG, Pmode, 3), src_mem,
668 remainder, align, most);
671 /* Emit code to perform a block move with an offset sequence of ld/st
672 instructions (..., ld 0, st 1, ld 1, st 0, ...). SIZE and ALIGN are
673 known constants. DEST and SRC are registers. OFFSET is the known
674 starting point for the output pattern. */
677 block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset)
685 enum machine_mode mode[2];
690 int offset_ld = offset;
691 int offset_st = offset;
693 active[0] = active[1] = FALSE;
695 /* Establish parameters for the first load and for the second load if
696 it is known to be the same mode as the first. */
697 amount[0] = amount[1] = align;
698 mode[0] = mode_from_align[align];
699 temp[0] = gen_reg_rtx (mode[0]);
700 if (size >= 2 * align)
703 temp[1] = gen_reg_rtx (mode[1]);
714 /* Change modes as the sequence tails off. */
715 if (size < amount[next])
717 amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1));
718 mode[next] = mode_from_align[amount[next]];
719 temp[next] = gen_reg_rtx (mode[next]);
721 size -= amount[next];
723 MEM_IN_STRUCT_P (src_mem) ? mode[next] : BLKmode,
724 gen_rtx (PLUS, Pmode, src,
725 gen_rtx (CONST_INT, SImode, offset_ld)));
726 RTX_UNCHANGING_P (srcp) = RTX_UNCHANGING_P (src_mem);
727 MEM_VOLATILE_P (srcp) = MEM_VOLATILE_P (src_mem);
728 MEM_IN_STRUCT_P (srcp) = MEM_IN_STRUCT_P (src_mem);
729 emit_insn (gen_rtx (SET, VOIDmode, temp[next], srcp));
730 offset_ld += amount[next];
736 active[phase] = FALSE;
738 MEM_IN_STRUCT_P (dest_mem) ? mode[phase] : BLKmode,
739 gen_rtx (PLUS, Pmode, dest,
740 gen_rtx (CONST_INT, SImode, offset_st)));
741 RTX_UNCHANGING_P (dstp) = RTX_UNCHANGING_P (dest_mem);
742 MEM_VOLATILE_P (dstp) = MEM_VOLATILE_P (dest_mem);
743 MEM_IN_STRUCT_P (dstp) = MEM_IN_STRUCT_P (dest_mem);
744 emit_insn (gen_rtx (SET, VOIDmode, dstp, temp[phase]));
745 offset_st += amount[phase];
748 while (active[next]);
751 /* Emit the code to do an AND operation. */
754 output_and (operands)
759 if (REG_P (operands[2]))
760 return "and %0,%1,%2";
762 value = INTVAL (operands[2]);
763 if (SMALL_INTVAL (value))
764 return "mask %0,%1,%2";
765 else if ((value & 0xffff0000) == 0xffff0000)
766 return "and %0,%1,%x2";
767 else if ((value & 0xffff) == 0xffff)
768 return "and.u %0,%1,%X2";
769 else if ((value & 0xffff) == 0)
770 return "mask.u %0,%1,%X2";
771 else if (integer_ok_for_set (~value))
772 return "clr %0,%1,%S2";
774 return "and.u %0,%1,%X2\n\tand %0,%0,%x2";
777 /* Emit the code to do an inclusive OR operation. */
780 output_ior (operands)
785 if (REG_P (operands[2]))
786 return "or %0,%1,%2";
788 value = INTVAL (operands[2]);
789 if (SMALL_INTVAL (value))
790 return "or %0,%1,%2";
791 else if ((value & 0xffff) == 0)
792 return "or.u %0,%1,%X2";
793 else if (integer_ok_for_set (value))
794 return "set %0,%1,%s2";
796 return "or.u %0,%1,%X2\n\tor %0,%0,%x2";
799 /* Emit the instructions for doing an XOR. */
802 output_xor (operands)
807 if (REG_P (operands[2]))
808 return "xor %0,%1,%2";
810 value = INTVAL (operands[2]);
811 if (SMALL_INTVAL (value))
812 return "xor %0,%1,%2";
813 else if ((value & 0xffff) == 0)
814 return "xor.u %0,%1,%X2";
816 return "xor.u %0,%1,%X2\n\txor %0,%0,%x2";
819 /* Output a call. Normally this is just bsr or jsr, but this also deals with
820 accomplishing a branch after the call by incrementing r1. This requires
821 that various assembler bugs be accommodated. The 4.30 DG/UX assembler
822 requires that forward references not occur when computing the difference of
823 two labels. The [version?] Motorola assembler computes a word difference.
824 No doubt there's more to come!
826 It would seem the same idea could be used to tail call, but in this case,
827 the epilogue will be non-null. */
829 static rtx sb_name = 0;
830 static rtx sb_high = 0;
831 static rtx sb_low = 0;
834 output_call (operands, addr)
844 /* This can be generalized, but there is currently no need. */
845 if (XVECLEN (final_sequence, 0) != 2)
848 /* The address of interior insns is not computed, so use the sequence. */
849 seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
850 jump = XVECEXP (final_sequence, 0, 1);
851 if (GET_CODE (jump) == JUMP_INSN)
855 rtx dest = XEXP (SET_SRC (PATTERN (jump)), 0);
856 int delta = 4 * (insn_addresses[INSN_UID (dest)]
857 - insn_addresses[INSN_UID (seq_insn)]
859 #if (MONITOR_GCC & 0x2) /* How often do long branches happen? */
860 if ((unsigned) (delta + 0x8000) >= 0x10000)
861 warning ("Internal gcc monitor: short-branch(%x)", delta);
864 /* Delete the jump. */
865 PUT_CODE (jump, NOTE);
866 NOTE_LINE_NUMBER (jump) = NOTE_INSN_DELETED;
867 NOTE_SOURCE_FILE (jump) = 0;
869 /* We only do this optimization if -O2, modifying the value of
870 r1 in the delay slot confuses debuggers and profilers on some
873 If we loose, we must use the non-delay form. This is unlikely
874 to ever happen. If it becomes a problem, claim that a call
875 has two delay slots and only the second can be filled with
878 The 88110 can lose when a jsr.n r1 is issued and a page fault
879 occurs accessing the delay slot. So don't use jsr.n form when
882 #ifdef AS_BUG_IMMEDIATE_LABEL /* The assembler restricts immediate values. */
884 || ! ADD_INTVAL (delta * 2)
887 || ! ADD_INTVAL (delta)
889 || (REG_P (addr) && REGNO (addr) == 1))
895 ? "bsr %0#plt\n\tbr %l1"
896 : "bsr %0\n\tbr %l1"));
899 /* Output the short branch form. */
900 output_asm_insn ((REG_P (addr)
902 : (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")),
907 ? "subu %#r1,%#r1,.-%l0+4"
908 : "addu %#r1,%#r1,%l0-.-4");
911 operands[0] = gen_label_rtx ();
912 operands[1] = gen_label_rtx ();
917 last = "subu %#r1,%#r1,%l0\n%l1:";
923 last = "addu %#r1,%#r1,%l0\n%l1:";
926 /* Record the values to be computed later as "def name,high-low". */
927 sb_name = gen_rtx (EXPR_LIST, VOIDmode, operands[0], sb_name);
928 sb_high = gen_rtx (EXPR_LIST, VOIDmode, high, sb_high);
929 sb_low = gen_rtx (EXPR_LIST, VOIDmode, low, sb_low);
930 #endif /* Don't USE_GAS */
937 : (flag_pic ? "bsr%. %0#plt" : "bsr%. %0"));
941 output_short_branch_defs (stream)
944 char name[256], high[256], low[256];
946 for (; sb_name && sb_high && sb_low;
947 sb_name = XEXP (sb_name, 1),
948 sb_high = XEXP (sb_high, 1),
949 sb_low = XEXP (sb_low, 1))
951 ASM_GENERATE_INTERNAL_LABEL
952 (name, "L", CODE_LABEL_NUMBER (XEXP (sb_name, 0)));
953 ASM_GENERATE_INTERNAL_LABEL
954 (high, "L", CODE_LABEL_NUMBER (XEXP (sb_high, 0)));
955 ASM_GENERATE_INTERNAL_LABEL
956 (low, "L", CODE_LABEL_NUMBER (XEXP (sb_low, 0)));
957 /* This will change as the assembler requirements become known. */
958 fprintf (stream, "\t%s\t %s,%s-%s\n",
959 SET_ASM_OP, &name[1], &high[1], &low[1]);
961 if (sb_name || sb_high || sb_low)
965 /* Return truth value of the statement that this conditional branch is likely
966 to fall through. CONDITION, is the condition that JUMP_INSN is testing. */
969 mostly_false_jump (jump_insn, condition)
970 rtx jump_insn, condition;
972 rtx target_label = JUMP_LABEL (jump_insn);
975 /* Much of this isn't computed unless we're optimizing. */
979 /* Determine if one path or the other leads to a return. */
980 for (insnt = NEXT_INSN (target_label);
982 insnt = NEXT_INSN (insnt))
984 if (GET_CODE (insnt) == JUMP_INSN)
986 else if (GET_CODE (insnt) == INSN
987 && GET_CODE (PATTERN (insnt)) == SEQUENCE
988 && GET_CODE (XVECEXP (PATTERN (insnt), 0, 0)) == JUMP_INSN)
990 insnt = XVECEXP (PATTERN (insnt), 0, 0);
995 && (GET_CODE (PATTERN (insnt)) == RETURN
996 || (GET_CODE (PATTERN (insnt)) == SET
997 && GET_CODE (SET_SRC (PATTERN (insnt))) == REG
998 && REGNO (SET_SRC (PATTERN (insnt))) == 1)))
1001 for (insnj = NEXT_INSN (jump_insn);
1003 insnj = NEXT_INSN (insnj))
1005 if (GET_CODE (insnj) == JUMP_INSN)
1007 else if (GET_CODE (insnj) == INSN
1008 && GET_CODE (PATTERN (insnj)) == SEQUENCE
1009 && GET_CODE (XVECEXP (PATTERN (insnj), 0, 0)) == JUMP_INSN)
1011 insnj = XVECEXP (PATTERN (insnj), 0, 0);
1016 && (GET_CODE (PATTERN (insnj)) == RETURN
1017 || (GET_CODE (PATTERN (insnj)) == SET
1018 && GET_CODE (SET_SRC (PATTERN (insnj))) == REG
1019 && REGNO (SET_SRC (PATTERN (insnj))) == 1)))
1022 /* Predict to not return. */
1023 if ((insnt == 0) != (insnj == 0))
1024 return (insnt == 0);
1026 /* Predict loops to loop. */
1027 for (insnt = PREV_INSN (target_label);
1028 insnt && GET_CODE (insnt) == NOTE;
1029 insnt = PREV_INSN (insnt))
1030 if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_END)
1032 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_BEG)
1034 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_CONT)
1037 /* Predict backward branches usually take. */
1039 insnj = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
1042 if (insn_addresses[INSN_UID (insnj)]
1043 > insn_addresses[INSN_UID (target_label)])
1046 /* EQ tests are usually false and NE tests are usually true. Also,
1047 most quantities are positive, so we can make the appropriate guesses
1048 about signed comparisons against zero. Consider unsigned comparisons
1049 to be a range check and assume quantities to be in range. */
1050 switch (GET_CODE (condition))
1053 /* Unconditional branch. */
1062 case GTU: /* Must get casesi right at least. */
1063 if (XEXP (condition, 1) == const0_rtx)
1070 if (XEXP (condition, 1) == const0_rtx)
1078 /* Return true if the operand is a power of two and is a floating
1079 point type (to optimize division by power of two into multiplication). */
1082 real_power_of_2_operand (op, mode)
1084 enum machine_mode mode;
1088 int i[sizeof (REAL_VALUE_TYPE) / sizeof (int)];
1089 struct { /* IEEE double precision format */
1091 unsigned exponent : 11;
1092 unsigned mantissa1 : 20;
1095 struct { /* IEEE double format to quick check */
1096 unsigned sign : 1; /* if it fits in a float */
1097 unsigned exponent1 : 4;
1098 unsigned exponent2 : 7;
1099 unsigned mantissa1 : 20;
1104 if (GET_MODE (op) != DFmode && GET_MODE (op) != SFmode)
1107 if (GET_CODE (op) != CONST_DOUBLE)
1110 u.i[0] = CONST_DOUBLE_LOW (op);
1111 u.i[1] = CONST_DOUBLE_HIGH (op);
1113 if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0 /* not a power of two */
1114 || u.s.exponent == 0 /* constant 0.0 */
1115 || u.s.exponent == 0x7ff /* NAN */
1116 || (u.s2.exponent1 != 0x8 && u.s2.exponent1 != 0x7))
1117 return 0; /* const won't fit in float */
1122 /* Make OP legitimate for mode MODE. Currently this only deals with DFmode
1123 operands, putting them in registers and making CONST_DOUBLE values
1124 SFmode where possible. */
1127 legitimize_operand (op, mode)
1129 enum machine_mode mode;
1133 union real_extract r;
1134 struct { /* IEEE double precision format */
1136 unsigned exponent : 11;
1137 unsigned mantissa1 : 20;
1140 struct { /* IEEE double format to quick check */
1141 unsigned sign : 1; /* if it fits in a float */
1142 unsigned exponent1 : 4;
1143 unsigned exponent2 : 7;
1144 unsigned mantissa1 : 20;
1149 if (GET_CODE (op) == REG || mode != DFmode)
1152 if (GET_CODE (op) == CONST_DOUBLE)
1154 bcopy (&CONST_DOUBLE_LOW (op), &u.r, sizeof u);
1155 if (u.d.exponent != 0x7ff /* NaN */
1156 && u.d.mantissa2 == 0 /* Mantissa fits */
1157 && (u.s.exponent1 == 0x8 || u.s.exponent1 == 0x7) /* Exponent fits */
1158 && (temp = simplify_unary_operation (FLOAT_TRUNCATE, SFmode,
1160 return gen_rtx (FLOAT_EXTEND, mode, force_reg (SFmode, temp));
1162 else if (register_operand (op, mode))
1165 return force_reg (mode, op);
1168 /* Return true if OP is a suitable input for a move insn. */
1171 move_operand (op, mode)
1173 enum machine_mode mode;
1175 if (register_operand (op, mode))
1177 if (GET_CODE (op) == CONST_INT)
1178 return (classify_integer (mode, INTVAL (op)) < m88k_oru_hi16);
1179 if (GET_MODE (op) != mode)
1181 if (GET_CODE (op) == SUBREG)
1182 op = SUBREG_REG (op);
1183 if (GET_CODE (op) != MEM)
1187 if (GET_CODE (op) == LO_SUM)
1188 return (REG_P (XEXP (op, 0))
1189 && symbolic_address_p (XEXP (op, 1)));
1190 return memory_address_p (mode, op);
1193 /* Return true if OP is suitable for a call insn. */
1196 call_address_operand (op, mode)
1198 enum machine_mode mode;
1200 return (REG_P (op) || symbolic_address_p (op));
1203 /* Returns true if OP is either a symbol reference or a sum of a symbol
1204 reference and a constant. */
1207 symbolic_address_p (op)
1210 switch (GET_CODE (op))
1218 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1219 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1220 && GET_CODE (XEXP (op, 1)) == CONST_INT);
1227 /* Return true if OP is a register or const0_rtx. */
1230 reg_or_0_operand (op, mode)
1232 enum machine_mode mode;
1234 return (op == const0_rtx || register_operand (op, mode));
1237 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
1240 arith_operand (op, mode)
1242 enum machine_mode mode;
1244 return (register_operand (op, mode)
1245 || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
1248 /* Return true if OP is a register or 5 bit integer. */
1251 arith5_operand (op, mode)
1253 enum machine_mode mode;
1255 return (register_operand (op, mode)
1256 || (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32));
1260 arith32_operand (op, mode)
1262 enum machine_mode mode;
1264 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
1268 arith64_operand (op, mode)
1270 enum machine_mode mode;
1272 return (register_operand (op, mode)
1273 || GET_CODE (op) == CONST_INT
1274 || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DImode));
1278 int5_operand (op, mode)
1280 enum machine_mode mode;
1282 return (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32);
1286 int32_operand (op, mode)
1288 enum machine_mode mode;
1290 return (GET_CODE (op) == CONST_INT);
1293 /* Return true if OP is a register or a valid immediate operand for
1297 add_operand (op, mode)
1299 enum machine_mode mode;
1301 return (register_operand (op, mode)
1302 || (GET_CODE (op) == CONST_INT && ADD_INT (op)));
1305 /* Nonzero if this is a bitmask filling the bottom bits, for optimizing and +
1306 shift left combinations into a single mak instruction. */
1312 return (value && POWER_OF_2_or_0 (value + 1));
1316 reg_or_bbx_mask_operand (op, mode)
1318 enum machine_mode mode;
1321 if (register_operand (op, mode))
1323 if (GET_CODE (op) != CONST_INT)
1326 value = INTVAL (op);
1327 if (POWER_OF_2 (value))
1333 /* Return true if OP is valid to use in the context of a floating
1334 point operation. Special case 0.0, since we can use r0. */
1337 real_or_0_operand (op, mode)
1339 enum machine_mode mode;
1341 if (mode != SFmode && mode != DFmode)
1344 return (register_operand (op, mode)
1345 || (GET_CODE (op) == CONST_DOUBLE
1346 && op == CONST0_RTX (mode)));
1349 /* Return true if OP is valid to use in the context of logic aritmethic
1350 on condition codes. */
1353 partial_ccmode_register_operand (op, mode)
1355 enum machine_mode mode;
1357 return register_operand (op, CCmode) || register_operand (op, CCEVENmode);
1360 /* Return true if OP is a relational operator. */
1365 enum machine_mode mode;
1367 switch (GET_CODE (op))
1386 even_relop (op, mode)
1388 enum machine_mode mode;
1390 switch (GET_CODE (op))
1404 odd_relop (op, mode)
1406 enum machine_mode mode;
1408 switch (GET_CODE (op))
1421 /* Return true if OP is a relational operator, and is not an unsigned
1422 relational operator. */
1425 relop_no_unsigned (op, mode)
1427 enum machine_mode mode;
1429 switch (GET_CODE (op))
1437 /* @@ What is this test doing? Why not use `mode'? */
1438 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
1439 || GET_MODE (op) == DImode
1440 || GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_FLOAT
1441 || GET_MODE (XEXP (op, 0)) == DImode
1442 || GET_MODE_CLASS (GET_MODE (XEXP (op, 1))) == MODE_FLOAT
1443 || GET_MODE (XEXP (op, 1)) == DImode)
1451 /* Return true if the code of this rtx pattern is EQ or NE. */
1454 equality_op (op, mode)
1456 enum machine_mode mode;
1458 return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
1461 /* Return true if the code of this rtx pattern is pc or label_ref. */
1464 pc_or_label_ref (op, mode)
1466 enum machine_mode mode;
1468 return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF);
1471 /* Output to FILE the start of the assembler file. */
1481 output_option (file, sep, type, name, indent, pos, max)
1490 if (strlen (sep) + strlen (type) + strlen (name) + pos > max)
1492 fprintf (file, indent);
1493 return fprintf (file, "%s%s", type, name);
1495 return pos + fprintf (file, "%s%s%s", sep, type, name);
1498 static struct { char *name; int value; } m_options[] = TARGET_SWITCHES;
1501 output_options (file, f_options, f_len, W_options, W_len,
1502 pos, max, sep, indent, term)
1504 struct option *f_options;
1505 struct option *W_options;
1515 pos = output_option (file, sep, "-O", "", indent, pos, max);
1516 if (write_symbols != NO_DEBUG)
1517 pos = output_option (file, sep, "-g", "", indent, pos, max);
1518 if (flag_traditional)
1519 pos = output_option (file, sep, "-traditional", "", indent, pos, max);
1521 pos = output_option (file, sep, "-p", "", indent, pos, max);
1522 if (profile_block_flag)
1523 pos = output_option (file, sep, "-a", "", indent, pos, max);
1525 for (j = 0; j < f_len; j++)
1526 if (*f_options[j].variable == f_options[j].on_value)
1527 pos = output_option (file, sep, "-f", f_options[j].string,
1530 for (j = 0; j < W_len; j++)
1531 if (*W_options[j].variable == W_options[j].on_value)
1532 pos = output_option (file, sep, "-W", W_options[j].string,
1535 for (j = 0; j < sizeof m_options / sizeof m_options[0]; j++)
1536 if (m_options[j].name[0] != '\0'
1537 && m_options[j].value > 0
1538 && ((m_options[j].value & target_flags)
1539 == m_options[j].value))
1540 pos = output_option (file, sep, "-m", m_options[j].name,
1543 if (m88k_short_data)
1544 pos = output_option (file, sep, "-mshort-data-", m88k_short_data,
1547 fprintf (file, term);
1551 output_file_start (file, f_options, f_len, W_options, W_len)
1553 struct option *f_options;
1554 struct option *W_options;
1559 ASM_FIRST_LINE (file);
1562 fprintf (file, "\t%s\n", REQUIRES_88110_ASM_OP);
1563 output_file_directive (file, main_input_filename);
1564 /* Switch to the data section so that the coffsem symbol and the
1565 gcc2_compiled. symbol aren't in the text section. */
1569 pos = fprintf (file, "\n; cc1 (%s) arguments:", VERSION_STRING);
1570 output_options (file, f_options, f_len, W_options, W_len,
1571 pos, 75, " ", "\n; ", "\n\n");
1573 if (TARGET_IDENTIFY_REVISION)
1577 time_t now = time ((time_t *)0);
1578 sprintf (indent, "]\"\n\t%s\t \"@(#)%s [", IDENT_ASM_OP, main_input_filename);
1579 fprintf (file, indent+3);
1580 pos = fprintf (file, "gcc %s, %.24s,", VERSION_STRING, ctime (&now));
1581 output_options (file, f_options, f_len, W_options, W_len,
1582 pos, 150 - strlen (indent), " ", indent, "]\"\n\n");
1586 /* Output an ascii string. */
1589 output_ascii (file, opcode, max, p, size)
1599 register int num = 0;
1601 fprintf (file, "\t%s\t \"", opcode);
1602 for (i = 0; i < size; i++)
1604 register int c = p[i];
1608 fprintf (file, "\"\n\t%s\t \"", opcode);
1612 if (c == '\"' || c == '\\')
1620 else if (in_escape && c >= '0' && c <= '9')
1622 /* If a digit follows an octal-escape, the Vax assembler fails
1623 to stop reading the escape after three digits. Continue to
1624 output the values as an octal-escape until a non-digit is
1626 fprintf (file, "\\%03o", c);
1629 else if (c >= ' ' && c < 0177)
1639 /* Some assemblers can't handle \a, \v, or \?. */
1640 case '\t': c = 't'; goto escape;
1641 case '\f': c = 'f'; goto escape;
1642 case '\b': c = 'b'; goto escape;
1643 case '\r': c = 'r'; goto escape;
1644 case '\n': c = 'n'; goto escape;
1647 fprintf (file, "\\%03o", c);
1652 fprintf (file, "\"\n");
1655 /* Output a label (allows insn-output.c to be compiled without including
1656 m88k.c or needing to include stdio.h). */
1659 output_label (label_number)
1662 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", label_number);
1665 /* Generate the assembly code for function entry.
1667 The prologue is responsible for setting up the stack frame,
1668 initializing the frame pointer register, saving registers that must be
1669 saved, and allocating SIZE additional bytes of storage for the
1670 local variables. SIZE is an integer. FILE is a stdio
1671 stream to which the assembler code should be output.
1673 The label for the beginning of the function need not be output by this
1674 macro. That has already been done when the macro is run.
1676 To determine which registers to save, the macro can refer to the array
1677 `regs_ever_live': element R is nonzero if hard register
1678 R is used anywhere within the function. This implies the
1679 function prologue should save register R, but not if it is one
1680 of the call-used registers.
1682 On machines where functions may or may not have frame-pointers, the
1683 function entry code must vary accordingly; it must set up the frame
1684 pointer if one is wanted, and not otherwise. To determine whether a
1685 frame pointer is in wanted, the macro can refer to the variable
1686 `frame_pointer_needed'. The variable's value will be 1 at run
1687 time in a function that needs a frame pointer.
1689 On machines where an argument may be passed partly in registers and
1690 partly in memory, this macro must examine the variable
1691 `current_function_pretend_args_size', and allocate that many bytes
1692 of uninitialized space on the stack just underneath the first argument
1693 arriving on the stack. (This may not be at the very end of the stack,
1694 if the calling sequence has pushed anything else since pushing the stack
1695 arguments. But usually, on such machines, nothing else has been pushed
1696 yet, because the function prologue itself does all the pushing.)
1698 If `ACCUMULATE_OUTGOING_ARGS' is defined, the variable
1699 `current_function_outgoing_args_size' contains the size in bytes
1700 required for the outgoing arguments. This macro must add that
1701 amount of uninitialized space to very bottom of the stack.
1703 The stack frame we use looks like this:
1706 |==============================================|
1708 |==============================================|
1709 | [caller's outgoing memory arguments] |
1710 |==============================================|
1711 | caller's outgoing argument area (32 bytes) |
1712 sp -> |==============================================| <- ap
1713 | [local variable space] |
1714 |----------------------------------------------|
1715 | [return address (r1)] |
1716 |----------------------------------------------|
1717 | [previous frame pointer (r30)] |
1718 |==============================================| <- fp
1719 | [preserved registers (r25..r14)] |
1720 |----------------------------------------------|
1721 | [preserved registers (x29..x22)] |
1722 |==============================================|
1723 | [dynamically allocated space (alloca)] |
1724 |==============================================|
1725 | [callee's outgoing memory arguments] |
1726 |==============================================|
1727 | [callee's outgoing argument area (32 bytes)] |
1728 |==============================================| <- sp
1732 r1 and r30 must be saved if debugging.
1734 fp (if present) is located two words down from the local
1738 static void emit_add ();
1739 static void preserve_registers ();
1740 static void emit_ldst ();
1741 static void output_tdesc ();
1745 static char save_regs[FIRST_PSEUDO_REGISTER];
1746 static int frame_laid_out;
1747 static int frame_size;
1748 static int variable_args_p;
1749 static int epilogue_marked;
1750 static int prologue_marked;
1752 extern char call_used_regs[];
1753 extern int current_function_pretend_args_size;
1754 extern int current_function_outgoing_args_size;
1755 extern int frame_pointer_needed;
1757 #define FIRST_OCS_PRESERVE_REGISTER 14
1758 #define LAST_OCS_PRESERVE_REGISTER 30
1760 #define FIRST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 22)
1761 #define LAST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 31)
1763 #define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
1764 #define ROUND_CALL_BLOCK_SIZE(BYTES) \
1765 (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
1767 /* Establish the position of the FP relative to the SP. This is done
1768 either during FUNCTION_PROLOGUE or by INITIAL_ELIMINATION_OFFSET. */
1771 m88k_layout_frame ()
1777 bzero ((char *) &save_regs[0], sizeof (save_regs));
1778 sp_size = nregs = nxregs = 0;
1779 frame_size = get_frame_size ();
1781 /* Since profiling requires a call, make sure r1 is saved. */
1782 if (profile_flag || profile_block_flag)
1785 /* If we are producing debug information, store r1 and r30 where the
1786 debugger wants to find them (r30 at r30+0, r1 at r30+4). Space has
1787 already been reserved for r1/r30 in STARTING_FRAME_OFFSET. */
1788 if (write_symbols != NO_DEBUG && !TARGET_OCS_FRAME_POSITION)
1791 /* If there is a call, alloca is used, __builtin_alloca is used, or
1792 a dynamic-sized object is defined, add the 8 additional words
1793 for the callee's argument area. The common denominator is that the
1794 FP is required. may_call_alloca only gets calls to alloca;
1795 current_function_calls_alloca gets alloca and __builtin_alloca. */
1796 if (regs_ever_live[1] || frame_pointer_needed)
1799 sp_size += REG_PARM_STACK_SPACE (0);
1802 /* If we are producing PIC, save the addressing base register and r1. */
1803 if (flag_pic && current_function_uses_pic_offset_table)
1805 save_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
1809 /* If a frame is requested, save the previous FP, and the return
1810 address (r1), so that a traceback can be done without using tdesc
1811 information. Otherwise, simply save the FP if it is used as
1812 a preserve register. */
1813 if (frame_pointer_needed)
1814 save_regs[FRAME_POINTER_REGNUM] = save_regs[1] = 1;
1815 else if (regs_ever_live[FRAME_POINTER_REGNUM])
1816 save_regs[FRAME_POINTER_REGNUM] = 1;
1818 /* Figure out which extended register(s) needs to be saved. */
1819 for (regno = FIRST_EXTENDED_REGISTER + 1; regno < FIRST_PSEUDO_REGISTER;
1821 if (regs_ever_live[regno] && ! call_used_regs[regno])
1823 save_regs[regno] = 1;
1827 /* Figure out which normal register(s) needs to be saved. */
1828 for (regno = 2; regno < FRAME_POINTER_REGNUM; regno++)
1829 if (regs_ever_live[regno] && ! call_used_regs[regno])
1831 save_regs[regno] = 1;
1835 /* Achieve greatest use of double memory ops. Either we end up saving
1836 r30 or we use that slot to align the registers we do save. */
1837 if (nregs >= 2 && save_regs[1] && !save_regs[FRAME_POINTER_REGNUM])
1840 nregs += save_regs[1] + save_regs[FRAME_POINTER_REGNUM];
1841 /* if we need to align extended registers, add a word */
1842 if (nxregs > 0 && (nregs & 1) != 0)
1844 sp_size += 4 * nregs;
1845 sp_size += 8 * nxregs;
1846 sp_size += current_function_outgoing_args_size;
1848 /* The first two saved registers are placed above the new frame pointer
1849 if any. In the only case this matters, they are r1 and r30. */
1850 if (frame_pointer_needed || sp_size)
1851 m88k_fp_offset = ROUND_CALL_BLOCK_SIZE (sp_size - STARTING_FRAME_OFFSET);
1853 m88k_fp_offset = -STARTING_FRAME_OFFSET;
1854 m88k_stack_size = m88k_fp_offset + STARTING_FRAME_OFFSET;
1856 /* First, combine m88k_stack_size and size. If m88k_stack_size is
1857 non-zero, align the frame size to 8 mod 16; otherwise align the
1858 frame size to 0 mod 16. (If stacks are 8 byte aligned, this ends
1862 = ((m88k_stack_size ? STACK_UNIT_BOUNDARY - STARTING_FRAME_OFFSET : 0)
1863 - (frame_size % STACK_UNIT_BOUNDARY));
1867 need += STACK_UNIT_BOUNDARY;
1868 (void) assign_stack_local (BLKmode, need, BITS_PER_UNIT);
1869 frame_size = get_frame_size ();
1872 = ROUND_CALL_BLOCK_SIZE (m88k_stack_size + frame_size
1873 + current_function_pretend_args_size);
1877 /* Return true if this function is known to have a null prologue. */
1882 if (! reload_completed)
1884 if (! frame_laid_out)
1885 m88k_layout_frame ();
1886 return (! frame_pointer_needed
1889 && m88k_stack_size == 0);
1892 /* Determine if the current function has any references to the arg pointer.
1893 This is done indirectly by examining the DECL_ARGUMENTS' DECL_RTL.
1894 It is OK to return TRUE if there are no references, but FALSE must be
1902 if (current_function_decl == 0
1903 || current_function_varargs
1907 for (parm = DECL_ARGUMENTS (current_function_decl);
1909 parm = TREE_CHAIN (parm))
1911 if (DECL_RTL (parm) == 0
1912 || GET_CODE (DECL_RTL (parm)) == MEM)
1915 if (DECL_INCOMING_RTL (parm) == 0
1916 || GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
1923 m88k_begin_prologue (stream, size)
1927 m88k_prologue_done = 1; /* it's ok now to put out ln directives */
1931 m88k_end_prologue (stream)
1934 if (TARGET_OCS_DEBUG_INFO && !prologue_marked)
1936 PUT_OCS_FUNCTION_START (stream);
1937 prologue_marked = 1;
1939 /* If we've already passed the start of the epilogue, say that
1940 it starts here. This marks the function as having a null body,
1941 but at a point where the return address is in a known location.
1943 Originally, I thought this couldn't happen, but the pic prologue
1944 for leaf functions ends with the instruction that restores the
1945 return address from the temporary register. If the temporary
1946 register is never used, that instruction can float all the way
1947 to the end of the function. */
1948 if (epilogue_marked)
1949 PUT_OCS_FUNCTION_END (stream);
1954 m88k_expand_prologue ()
1956 m88k_layout_frame ();
1958 if (TARGET_OPTIMIZE_ARG_AREA
1960 && ! uses_arg_area_p ())
1962 /* The incoming argument area is used for stack space if it is not
1963 used (or if -mno-optimize-arg-area is given). */
1964 if ((m88k_stack_size -= REG_PARM_STACK_SPACE (0)) < 0)
1965 m88k_stack_size = 0;
1968 if (m88k_stack_size)
1969 emit_add (stack_pointer_rtx, stack_pointer_rtx, -m88k_stack_size);
1971 if (nregs || nxregs)
1972 preserve_registers (m88k_fp_offset + 4, 1);
1974 if (frame_pointer_needed)
1975 emit_add (frame_pointer_rtx, stack_pointer_rtx, m88k_fp_offset);
1977 if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM])
1979 rtx return_reg = gen_rtx (REG, SImode, 1);
1980 rtx label = gen_label_rtx ();
1985 temp_reg = gen_rtx (REG, SImode, TEMP_REGNUM);
1986 emit_move_insn (temp_reg, return_reg);
1988 emit_insn (gen_locate1 (pic_offset_table_rtx, label));
1989 emit_insn (gen_locate2 (pic_offset_table_rtx, label));
1990 emit_insn (gen_addsi3 (pic_offset_table_rtx,
1991 pic_offset_table_rtx, return_reg));
1993 emit_move_insn (return_reg, temp_reg);
1995 if (profile_flag || profile_block_flag)
1996 emit_insn (gen_blockage ());
1999 /* This function generates the assembly code for function exit,
2000 on machines that need it. Args are same as for FUNCTION_PROLOGUE.
2002 The function epilogue should not depend on the current stack pointer!
2003 It should use the frame pointer only, if there is a frame pointer.
2004 This is mandatory because of alloca; we also take advantage of it to
2005 omit stack adjustments before returning. */
2008 m88k_begin_epilogue (stream)
2011 if (TARGET_OCS_DEBUG_INFO && !epilogue_marked && prologue_marked)
2013 PUT_OCS_FUNCTION_END (stream);
2015 epilogue_marked = 1;
2019 m88k_end_epilogue (stream, size)
2023 rtx insn = get_last_insn ();
2025 if (TARGET_OCS_DEBUG_INFO && !epilogue_marked)
2026 PUT_OCS_FUNCTION_END (stream);
2028 /* If the last insn isn't a BARRIER, we must write a return insn. This
2029 should only happen if the function has no prologe and no body. */
2030 if (GET_CODE (insn) == NOTE)
2031 insn = prev_nonnote_insn (insn);
2032 if (insn == 0 || GET_CODE (insn) != BARRIER)
2033 fprintf (stream, "\tjmp\t %s\n", reg_names[1]);
2035 output_short_branch_defs (stream);
2037 fprintf (stream, "\n");
2039 if (TARGET_OCS_DEBUG_INFO)
2040 output_tdesc (stream, m88k_fp_offset + 4);
2042 m88k_function_number++;
2043 m88k_prologue_done = 0; /* don't put out ln directives */
2044 variable_args_p = 0; /* has variable args */
2046 epilogue_marked = 0;
2047 prologue_marked = 0;
2051 m88k_expand_epilogue ()
2053 #if (MONITOR_GCC & 0x4) /* What are interesting prologue/epilogue values? */
2054 fprintf (stream, "; size = %d, m88k_fp_offset = %d, m88k_stack_size = %d\n",
2055 size, m88k_fp_offset, m88k_stack_size);
2058 if (frame_pointer_needed)
2059 emit_add (stack_pointer_rtx, frame_pointer_rtx, -m88k_fp_offset);
2061 if (nregs || nxregs)
2062 preserve_registers (m88k_fp_offset + 4, 0);
2064 if (m88k_stack_size)
2065 emit_add (stack_pointer_rtx, stack_pointer_rtx, m88k_stack_size);
2068 /* Emit insns to set DSTREG to SRCREG + AMOUNT during the prologue or
2072 emit_add (dstreg, srcreg, amount)
2077 rtx incr = gen_rtx (CONST_INT, VOIDmode, abs (amount));
2078 if (! ADD_INTVAL (amount))
2080 rtx temp = gen_rtx (REG, SImode, TEMP_REGNUM);
2081 emit_move_insn (temp, incr);
2084 emit_insn ((amount < 0 ? gen_subsi3 : gen_addsi3) (dstreg, srcreg, incr));
2087 /* Save/restore the preserve registers. base is the highest offset from
2088 r31 at which a register is stored. store_p is true if stores are to
2089 be done; otherwise loads. */
2092 preserve_registers (base, store_p)
2101 } mem_op[FIRST_PSEUDO_REGISTER];
2102 struct mem_op *mo_ptr = mem_op;
2104 /* The 88open OCS mandates that preserved registers be stored in
2105 increasing order. For compatibility with current practice,
2106 the order is r1, r30, then the preserve registers. */
2111 /* An extra word is given in this case to make best use of double
2113 if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM])
2115 emit_ldst (store_p, 1, SImode, offset);
2120 /* Walk the registers to save recording all single memory operations. */
2121 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2122 if (save_regs[regno])
2124 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2127 mo_ptr->regno = regno;
2128 mo_ptr->offset = offset;
2139 /* Walk the registers to save recording all double memory operations.
2140 This avoids a delay in the epilogue (ld.d/ld). */
2142 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2143 if (save_regs[regno])
2145 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2152 mo_ptr->regno = regno-1;
2153 mo_ptr->offset = offset-4;
2160 /* Walk the extended registers to record all memory operations. */
2161 /* Be sure the offset is double word aligned. */
2162 offset = (offset - 1) & ~7;
2163 for (regno = FIRST_PSEUDO_REGISTER - 1; regno > FIRST_EXTENDED_REGISTER;
2165 if (save_regs[regno])
2168 mo_ptr->regno = regno;
2169 mo_ptr->offset = offset;
2176 /* Output the memory operations. */
2177 for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++)
2180 emit_ldst (store_p, mo_ptr->regno,
2181 (mo_ptr->nregs > 1 ? DImode : SImode),
2187 emit_ldst (store_p, regno, mode, offset)
2190 enum machine_mode mode;
2193 rtx reg = gen_rtx (REG, mode, regno);
2196 if (SMALL_INTVAL (offset))
2198 mem = gen_rtx (MEM, mode, plus_constant (stack_pointer_rtx, offset));
2202 /* offset is too large for immediate index must use register */
2204 rtx disp = gen_rtx (CONST_INT, VOIDmode, offset);
2205 rtx temp = gen_rtx (REG, SImode, TEMP_REGNUM);
2206 rtx regi = gen_rtx (PLUS, SImode, stack_pointer_rtx, temp);
2207 emit_move_insn (temp, disp);
2208 mem = gen_rtx (MEM, mode, regi);
2212 emit_move_insn (mem, reg);
2214 emit_move_insn (reg, mem);
2217 /* Convert the address expression REG to a CFA offset. */
2220 m88k_debugger_offset (reg, offset)
2222 register int offset;
2224 if (GET_CODE (reg) == PLUS)
2226 offset = INTVAL (XEXP (reg, 1));
2227 reg = XEXP (reg, 0);
2230 /* Put the offset in terms of the CFA (arg pointer). */
2231 if (reg == frame_pointer_rtx)
2232 offset += m88k_fp_offset - m88k_stack_size;
2233 else if (reg == stack_pointer_rtx)
2234 offset -= m88k_stack_size;
2235 else if (reg != arg_pointer_rtx)
2237 #if (MONITOR_GCC & 0x10) /* Watch for suspicious symbolic locations. */
2238 if (! (GET_CODE (reg) == REG
2239 && REGNO (reg) >= FIRST_PSEUDO_REGISTER))
2240 warning ("Internal gcc error: Can't express symbolic location");
2248 /* Output the 88open OCS proscribed text description information.
2251 0 22: info-byte-length (16 or 20 bytes)
2252 0 2: info-alignment (word 2)
2253 1 32: info-protocol (version 1 or 2(pic))
2254 2 32: starting-address (inclusive, not counting prologue)
2255 3 32: ending-address (exclusive, not counting epilog)
2256 4 8: info-variant (version 1 or 3(extended registers))
2257 4 17: register-save-mask (from register 14 to 30)
2259 4 1: return-address-info-discriminant
2260 4 5: frame-address-register
2261 5 32: frame-address-offset
2262 6 32: return-address-info
2263 7 32: register-save-offset
2264 8 16: extended-register-save-mask (x16 - x31)
2265 8 16: extended-register-save-offset (WORDS from register-save-offset) */
2268 output_tdesc (file, offset)
2273 long mask, return_address_info, register_save_offset;
2274 long xmask, xregister_save_offset;
2277 for (mask = 0, i = 0, regno = FIRST_OCS_PRESERVE_REGISTER;
2278 regno <= LAST_OCS_PRESERVE_REGISTER;
2282 if (save_regs[regno])
2289 for (xmask = 0, j = 0, regno = FIRST_OCS_EXTENDED_PRESERVE_REGISTER;
2290 regno <= LAST_OCS_EXTENDED_PRESERVE_REGISTER;
2294 if (save_regs[regno])
2303 if ((nxregs > 0 || nregs > 2) && !save_regs[FRAME_POINTER_REGNUM])
2305 return_address_info = - m88k_stack_size + offset;
2306 register_save_offset = return_address_info - i*4;
2310 return_address_info = 1;
2311 register_save_offset = - m88k_stack_size + offset + 4 - i*4;
2314 xregister_save_offset = - (j * 2 + ((register_save_offset >> 2) & 1));
2318 fprintf (file, "\t%s\t %d,%d", INT_ASM_OP, /* 8:0,22:(20 or 16),2:2 */
2319 (((xmask != 0) ? 20 : 16) << 2) | 2,
2322 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_START_PREFIX, m88k_function_number);
2323 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2324 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_END_PREFIX, m88k_function_number);
2325 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2327 fprintf (file, ",0x%x,0x%x,0x%x,0x%x",
2328 /* 8:1,17:0x%.3x,1:0,1:%d,5:%d */
2329 (((xmask ? 3 : 1) << (17+1+1+5))
2331 | ((!!save_regs[1]) << 5)
2332 | (frame_pointer_needed
2333 ? FRAME_POINTER_REGNUM
2334 : STACK_POINTER_REGNUM)),
2335 (m88k_stack_size - (frame_pointer_needed ? m88k_fp_offset : 0)),
2336 return_address_info,
2337 register_save_offset);
2339 fprintf (file, ",0x%x%04x", xmask, (0xffff & xregister_save_offset));
2345 /* Output assembler code to FILE to increment profiler label # LABELNO
2346 for profiling a function entry. NAME is the mcount function name
2347 (varies), SAVEP indicates whether the parameter registers need to
2348 be saved and restored. */
2351 output_function_profiler (file, labelno, name, savep)
2359 char *temp = (savep ? reg_names[2] : reg_names[10]);
2361 /* Remember to update FUNCTION_PROFILER_LENGTH. */
2365 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2366 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2367 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2368 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2369 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2372 ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno);
2375 fprintf (file, "\tor.u\t %s,%s,%shi16(%s#got_rel)\n",
2376 temp, reg_names[0], m88k_pound_sign, &label[1]);
2377 fprintf (file, "\tor\t %s,%s,%slo16(%s#got_rel)\n",
2378 temp, temp, m88k_pound_sign, &label[1]);
2379 sprintf (dbi, "\tld\t %s,%s,%s\n", temp,
2380 reg_names[PIC_OFFSET_TABLE_REGNUM], temp);
2384 sprintf (dbi, "\tld\t %s,%s,%s#got_rel\n", temp,
2385 reg_names[PIC_OFFSET_TABLE_REGNUM], &label[1]);
2389 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n",
2390 temp, reg_names[0], m88k_pound_sign, &label[1]);
2391 sprintf (dbi, "\tor\t %s,%s,%slo16(%s)\n",
2392 temp, temp, m88k_pound_sign, &label[1]);
2396 fprintf (file, "\tbsr.n\t %s#plt\n", name);
2398 fprintf (file, "\tbsr.n\t %s\n", name);
2403 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2404 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2405 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2406 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2407 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2411 /* Output assembler code to FILE to initialize basic-block profiling for
2412 the current module. LABELNO is unique to each instance. */
2415 output_function_block_profiler (file, labelno)
2422 /* Remember to update FUNCTION_BLOCK_PROFILER_LENGTH. */
2424 ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 0);
2425 ASM_GENERATE_INTERNAL_LABEL (label, "LPY", labelno);
2427 /* @@ Need to deal with PIC. I'm not sure what the requirements are on
2428 register usage, so I used r26/r27 to be safe. */
2429 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n", reg_names[27], reg_names[0],
2430 m88k_pound_sign, &block[1]);
2431 fprintf (file, "\tld\t %s,%s,%slo16(%s)\n", reg_names[26], reg_names[27],
2432 m88k_pound_sign, &block[1]);
2433 fprintf (file, "\tbcnd\t %sne0,%s,%s\n",
2434 m88k_pound_sign, reg_names[26], &label[1]);
2435 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2436 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2437 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2438 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2439 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2440 fputs ("\tbsr.n\t ", file);
2441 ASM_OUTPUT_LABELREF (file, "__bb_init_func");
2443 fprintf (file, "\tor\t %s,%s,%slo16(%s)\n", reg_names[2], reg_names[27],
2444 m88k_pound_sign, &block[1]);
2445 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2446 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2447 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2448 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2449 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2450 ASM_OUTPUT_INTERNAL_LABEL (file, "LPY", labelno);
2453 /* Output assembler code to FILE to increment the count associated with
2454 the basic block number BLOCKNO. */
2457 output_block_profiler (file, blockno)
2463 /* Remember to update BLOCK_PROFILER_LENGTH. */
2465 ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 2);
2467 /* @@ Need to deal with PIC. I'm not sure what the requirements are on
2468 register usage, so I used r26/r27 to be safe. */
2469 fprintf (file, "\tor.u\t %s,%s,%shi16(%s+%d)\n", reg_names[27], reg_names[0],
2470 m88k_pound_sign, &block[1], 4 * blockno);
2471 fprintf (file, "\tld\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27],
2472 m88k_pound_sign, &block[1], 4 * blockno);
2473 fprintf (file, "\taddu\t %s,%s,1\n", reg_names[26], reg_names[26]);
2474 fprintf (file, "\tst\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27],
2475 m88k_pound_sign, &block[1], 4 * blockno);
2478 /* Determine whether a function argument is passed in a register, and
2481 The arguments are CUM, which summarizes all the previous
2482 arguments; MODE, the machine mode of the argument; TYPE,
2483 the data type of the argument as a tree node or 0 if that is not known
2484 (which happens for C support library functions); and NAMED,
2485 which is 1 for an ordinary argument and 0 for nameless arguments that
2486 correspond to `...' in the called function's prototype.
2488 The value of the expression should either be a `reg' RTX for the
2489 hard register in which to pass the argument, or zero to pass the
2490 argument on the stack.
2492 On the m88000 the first eight words of args are normally in registers
2493 and the rest are pushed. Double precision floating point must be
2494 double word aligned (and if in a register, starting on an even
2495 register). Structures and unions which are not 4 byte, and word
2496 aligned are passed in memory rather than registers, even if they
2497 would fit completely in the registers under OCS rules.
2499 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2500 For structures that are passed in memory, but could have been
2501 passed in registers, we first load the structure into the
2502 register, and then when the last argument is passed, we store
2503 the registers into the stack locations. This fixes some bugs
2504 where GCC did not expect to have register arguments, followed
2505 by stack arguments, followed by register arguments. */
2508 m88k_function_arg (args_so_far, mode, type, named)
2509 CUMULATIVE_ARGS args_so_far;
2510 enum machine_mode mode;
2516 if (type != 0 /* undo putting struct in register */
2517 && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
2520 if (mode == BLKmode && TARGET_WARN_PASS_STRUCT)
2521 warning ("argument #%d is a structure", args_so_far + 1);
2523 if ((args_so_far & 1) != 0
2524 && (mode == DImode || mode == DFmode
2525 || (type != 0 && TYPE_ALIGN (type) > 32)))
2530 return (rtx) 0; /* don't put args in registers */
2533 if (type == 0 && mode == BLKmode)
2534 abort (); /* m88k_function_arg argument `type' is NULL for BLKmode. */
2536 bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
2537 words = (bytes + 3) / 4;
2539 if (args_so_far + words > 8)
2540 return (rtx) 0; /* args have exhausted registers */
2542 else if (mode == BLKmode
2543 && (TYPE_ALIGN (type) != BITS_PER_WORD
2544 || bytes != UNITS_PER_WORD))
2547 return gen_rtx (REG,
2548 ((mode == BLKmode) ? TYPE_MODE (type) : mode),
2552 /* Do what is necessary for `va_start'. The argument is ignored;
2553 We look at the current function to determine if stdargs or varargs
2554 is used and fill in an initial va_list. A pointer to this constructor
2558 m88k_builtin_saveregs (arglist)
2561 rtx block, addr, argsize;
2562 tree fntype = TREE_TYPE (current_function_decl);
2563 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2564 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2565 != void_type_node)))
2566 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
2568 variable_args_p = 1;
2570 if (CONSTANT_P (current_function_arg_offset_rtx))
2572 fixed = (XINT (current_function_arg_offset_rtx, 0)
2573 + argadj) / UNITS_PER_WORD;
2574 argsize = gen_rtx (CONST_INT, VOIDmode, fixed);
2579 argsize = plus_constant (current_function_arg_offset_rtx, argadj);
2580 argsize = expand_shift (RSHIFT_EXPR, Pmode, argsize,
2581 build_int_2 (2, 0), argsize, 0);
2584 /* Allocate the va_list constructor */
2585 block = assign_stack_local (BLKmode, 3 * UNITS_PER_WORD, BITS_PER_WORD);
2586 RTX_UNCHANGING_P (block) = 1;
2587 RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
2589 /* Store the argsize as the __va_arg member. */
2590 emit_move_insn (change_address (block, SImode, XEXP (block, 0)),
2593 /* Store the arg pointer in the __va_stk member. */
2594 emit_move_insn (change_address (block, Pmode,
2595 plus_constant (XEXP (block, 0),
2597 copy_to_reg (virtual_incoming_args_rtx));
2599 /* Allocate the register space, and store it as the __va_reg member. */
2600 addr = assign_stack_local (BLKmode, 8 * UNITS_PER_WORD, -1);
2601 MEM_IN_STRUCT_P (addr) = 1;
2602 RTX_UNCHANGING_P (addr) = 1;
2603 RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
2604 emit_move_insn (change_address (block, Pmode,
2605 plus_constant (XEXP (block, 0),
2606 2 * UNITS_PER_WORD)),
2607 copy_to_reg (XEXP (addr, 0)));
2609 /* Now store the incoming registers. */
2613 change_address (addr, Pmode,
2614 plus_constant (XEXP (addr, 0),
2615 fixed * UNITS_PER_WORD)),
2616 8 - fixed, UNITS_PER_WORD * (8 - fixed));
2618 /* Return the address of the va_list constructor, but don't put it in a
2619 register. This fails when not optimizing and produces worse code when
2621 return XEXP (block, 0);
2624 /* If cmpsi has not been generated, emit code to do the test. Return the
2625 expression describing the test of operator OP. */
2628 emit_test (op, mode)
2630 enum machine_mode mode;
2632 if (m88k_compare_reg == 0)
2633 emit_insn (gen_test (m88k_compare_op0, m88k_compare_op1));
2634 return (gen_rtx (op, mode, m88k_compare_reg, const0_rtx));
2637 /* Determine how to best perform cmpsi/bxx, where cmpsi has a constant
2638 operand. All tests with zero (albeit swapped) and all equality tests
2639 with a constant are done with bcnd. The remaining cases are swapped
2643 emit_bcnd (op, label)
2647 if (m88k_compare_op1 == const0_rtx)
2648 emit_jump_insn (optimize
2649 ? gen_bxx (emit_test (op, VOIDmode), label)
2650 : gen_bcnd (gen_rtx (op, VOIDmode,
2651 m88k_compare_op0, const0_rtx),
2653 else if (m88k_compare_op0 == const0_rtx)
2654 emit_jump_insn (optimize
2655 ? gen_bxx (emit_test (op, VOIDmode), label)
2656 : gen_bcnd (gen_rtx (swap_condition (op), VOIDmode,
2657 m88k_compare_op1, const0_rtx),
2659 else if (op != EQ && op != NE)
2660 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2663 rtx zero = gen_reg_rtx (SImode);
2667 if (GET_CODE (m88k_compare_op1) == CONST_INT)
2669 reg = force_reg (SImode, m88k_compare_op0);
2670 constant = m88k_compare_op1;
2674 reg = force_reg (SImode, m88k_compare_op1);
2675 constant = m88k_compare_op0;
2677 value = INTVAL (constant);
2679 /* Perform an arithmetic computation to make the compared-to value
2680 zero, but avoid loosing if the bcnd is later changed into sxx. */
2681 if (SMALL_INTVAL (value))
2682 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2685 if (SMALL_INTVAL (-value))
2686 emit_insn (gen_addsi3 (zero, reg,
2687 gen_rtx (CONST_INT, VOIDmode, -value)));
2689 emit_insn (gen_xorsi3 (zero, reg, constant));
2691 emit_jump_insn (gen_bcnd (gen_rtx (op, VOIDmode,
2698 /* Print an operand. Recognize special options, documented below. */
2701 print_operand (file, x, code)
2706 enum rtx_code xc = (x ? GET_CODE (x) : UNKNOWN);
2707 register int value = (xc == CONST_INT ? INTVAL (x) : 0);
2708 static int sequencep;
2709 static int reversep;
2713 if (code < 'B' || code > 'E')
2714 output_operand_lossage ("%R not followed by %B/C/D/E");
2716 xc = reverse_condition (xc);
2722 case '*': /* addressing base register for PIC */
2723 fputs (reg_names[PIC_OFFSET_TABLE_REGNUM], file); return;
2725 case '#': /* SVR4 pound-sign syntax character (empty if SVR3) */
2726 fputs (m88k_pound_sign, file); return;
2728 case 'V': /* Output a serializing instruction as needed if the operand
2729 (assumed to be a MEM) is a volatile load. */
2730 case 'v': /* ditto for a volatile store. */
2731 if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE)
2733 /* The m88110 implements two FIFO queues, one for loads and
2734 one for stores. These queues mean that loads complete in
2735 their issue order as do stores. An interaction between the
2736 history buffer and the store reservation station ensures
2737 that a store will not bypass load. Finally, a load will not
2738 bypass store, but only when they reference the same address.
2740 To avoid this reordering (a load bypassing a store) for
2741 volatile references, a serializing instruction is output.
2742 We choose the fldcr instruction as it does not serialize on
2743 the m88100 so that -m88000 code will not be degraded.
2745 The mechanism below is completed by having CC_STATUS_INIT set
2746 the code to the unknown value. */
2750 A problem with 88110 4.1 & 4.2 makes the use of fldcr for
2751 this purpose undesirable. Instead we will use tb1, this will
2752 cause serialization on the 88100 but such is life.
2755 static rtx last_addr = 0;
2756 if (code == 'V' /* Only need to serialize before a load. */
2757 && m88k_volatile_code != 'V' /* Loads complete in FIFO order. */
2758 && !(m88k_volatile_code == 'v'
2759 && GET_CODE (XEXP (x, 0)) == LO_SUM
2760 && rtx_equal_p (XEXP (XEXP (x, 0), 1), last_addr)))
2764 "fldcr\t %s,%scr63\n\t",
2766 "fldcr\t %s,%sfcr63\n\t",
2768 reg_names[0], m88k_pound_sign);
2770 "tb1\t 1,%s,0xff\n\t", reg_names[0]);
2772 m88k_volatile_code = code;
2773 last_addr = (GET_CODE (XEXP (x, 0)) == LO_SUM
2774 ? XEXP (XEXP (x, 0), 1) : 0);
2778 case 'X': /* print the upper 16 bits... */
2780 case 'x': /* print the lower 16 bits of the integer constant in hex */
2781 if (xc != CONST_INT)
2782 output_operand_lossage ("invalid %x/X value");
2783 fprintf (file, "0x%x", value & 0xffff); return;
2785 case 'H': /* print the low 16 bits of the negated integer constant */
2786 if (xc != CONST_INT)
2787 output_operand_lossage ("invalid %H value");
2789 case 'h': /* print the register or low 16 bits of the integer constant */
2792 if (xc != CONST_INT)
2793 output_operand_lossage ("invalid %h value");
2794 fprintf (file, "%d", value & 0xffff);
2797 case 'Q': /* print the low 8 bits of the negated integer constant */
2798 if (xc != CONST_INT)
2799 output_operand_lossage ("invalid %Q value");
2801 case 'q': /* print the register or low 8 bits of the integer constant */
2804 if (xc != CONST_INT)
2805 output_operand_lossage ("invalid %q value");
2806 fprintf (file, "%d", value & 0xff);
2809 case 'w': /* print the integer constant (X == 32 ? 0 : 32 - X) */
2810 if (xc != CONST_INT)
2811 output_operand_lossage ("invalid %o value");
2812 fprintf (file, "%d", value == 32 ? 0 : 32 - value);
2815 case 'p': /* print the logarithm of the integer constant */
2817 || (value = exact_log2 (value)) < 0)
2818 output_operand_lossage ("invalid %p value");
2819 fprintf (file, "%d", value);
2822 case 'S': /* compliment the value and then... */
2824 case 's': /* print the width and offset values forming the integer
2825 constant with a SET instruction. See integer_ok_for_set. */
2827 register unsigned mask, uval = value;
2828 register int top, bottom;
2830 if (xc != CONST_INT)
2831 output_operand_lossage ("invalid %s/S value");
2832 /* All the "one" bits must be contiguous. If so, MASK will be
2833 a power of two or zero. */
2834 mask = (uval | (uval - 1)) + 1;
2835 if (!(uval && POWER_OF_2_or_0 (mask)))
2836 output_operand_lossage ("invalid %s/S value");
2837 top = mask ? exact_log2 (mask) : 32;
2838 bottom = exact_log2 (uval & ~(uval - 1));
2839 fprintf (file,"%d<%d>", top - bottom, bottom);
2843 case 'P': /* print nothing if pc_rtx; output label_ref */
2844 if (xc == LABEL_REF)
2845 output_addr_const (file, x);
2847 output_operand_lossage ("invalid %P operand");
2850 case 'L': /* print 0 or 1 if operand is label_ref and then... */
2851 fputc (xc == LABEL_REF ? '1' : '0', file);
2852 case '.': /* print .n if delay slot is used */
2853 fputs ((final_sequence
2854 && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
2855 ? ".n\t" : "\t", file);
2858 case '!': /* Reverse the following condition. */
2862 case 'R': /* reverse the condition of the next print_operand
2863 if operand is a label_ref. */
2865 reversep = (xc == LABEL_REF);
2868 case 'B': /* bcnd branch values */
2869 fputs (m88k_pound_sign, file);
2872 case EQ: fputs ("eq0", file); return;
2873 case NE: fputs ("ne0", file); return;
2874 case GT: fputs ("gt0", file); return;
2875 case LE: fputs ("le0", file); return;
2876 case LT: fputs ("lt0", file); return;
2877 case GE: fputs ("ge0", file); return;
2878 default: output_operand_lossage ("invalid %B value");
2881 case 'C': /* bb0/bb1 branch values for comparisons */
2882 fputs (m88k_pound_sign, file);
2885 case EQ: fputs ("eq", file); return;
2886 case NE: fputs ("ne", file); return;
2887 case GT: fputs ("gt", file); return;
2888 case LE: fputs ("le", file); return;
2889 case LT: fputs ("lt", file); return;
2890 case GE: fputs ("ge", file); return;
2891 case GTU: fputs ("hi", file); return;
2892 case LEU: fputs ("ls", file); return;
2893 case LTU: fputs ("lo", file); return;
2894 case GEU: fputs ("hs", file); return;
2895 default: output_operand_lossage ("invalid %C value");
2898 case 'D': /* bcnd branch values for float comparisons */
2901 case EQ: fputs ("0xa", file); return;
2902 case NE: fputs ("0x5", file); return;
2903 case GT: fputs (m88k_pound_sign, file);
2904 fputs ("gt0", file); return;
2905 case LE: fputs ("0xe", file); return;
2906 case LT: fputs ("0x4", file); return;
2907 case GE: fputs ("0xb", file); return;
2908 default: output_operand_lossage ("invalid %D value");
2911 case 'E': /* bcnd branch values for special integers */
2914 case EQ: fputs ("0x8", file); return;
2915 case NE: fputs ("0x7", file); return;
2916 default: output_operand_lossage ("invalid %E value");
2919 case 'd': /* second register of a two register pair */
2921 output_operand_lossage ("`%d' operand isn't a register");
2922 fputs (reg_names[REGNO (x) + 1], file);
2925 case 'r': /* an immediate 0 should be represented as `r0' */
2926 if (x == const0_rtx)
2928 fputs (reg_names[0], file);
2932 output_operand_lossage ("invalid %r value");
2938 if (REGNO (x) == ARG_POINTER_REGNUM)
2939 output_operand_lossage ("operand is r0");
2941 fputs (reg_names[REGNO (x)], file);
2943 else if (xc == PLUS)
2946 output_address (XEXP (x, 0));
2947 else if (flag_pic && xc == UNSPEC)
2949 output_addr_const (file, XVECEXP (x, 0, 0));
2950 fputs ("#got_rel", file);
2952 else if (xc == CONST_DOUBLE)
2953 output_operand_lossage ("operand is const_double");
2955 output_addr_const (file, x);
2958 case 'g': /* append #got_rel as needed */
2959 if (flag_pic && (xc == SYMBOL_REF || xc == LABEL_REF))
2961 output_addr_const (file, x);
2962 fputs ("#got_rel", file);
2967 case 'a': /* (standard), assume operand is an address */
2968 case 'c': /* (standard), assume operand is an immediate value */
2969 case 'l': /* (standard), assume operand is a label_ref */
2970 case 'n': /* (standard), like %c, except negate first */
2972 output_operand_lossage ("invalid code");
2977 print_operand_address (file, addr)
2981 register rtx reg0, reg1, temp;
2983 switch (GET_CODE (addr))
2986 if (REGNO (addr) == ARG_POINTER_REGNUM)
2989 fprintf (file, "%s,%s", reg_names[0], reg_names [REGNO (addr)]);
2993 fprintf (file, "%s,%slo16(",
2994 reg_names[REGNO (XEXP (addr, 0))], m88k_pound_sign);
2995 output_addr_const (file, XEXP (addr, 1));
3000 reg0 = XEXP (addr, 0);
3001 reg1 = XEXP (addr, 1);
3002 if (GET_CODE (reg0) == MULT || GET_CODE (reg0) == CONST_INT)
3009 if ((REG_P (reg0) && REGNO (reg0) == ARG_POINTER_REGNUM)
3010 || (REG_P (reg1) && REGNO (reg1) == ARG_POINTER_REGNUM))
3013 else if (REG_P (reg0))
3016 fprintf (file, "%s,%s",
3017 reg_names [REGNO (reg0)], reg_names [REGNO (reg1)]);
3019 else if (GET_CODE (reg1) == CONST_INT)
3020 fprintf (file, "%s,%d",
3021 reg_names [REGNO (reg0)], INTVAL (reg1));
3023 else if (GET_CODE (reg1) == MULT)
3025 rtx mreg = XEXP (reg1, 0);
3026 if (REGNO (mreg) == ARG_POINTER_REGNUM)
3029 fprintf (file, "%s[%s]", reg_names[REGNO (reg0)],
3030 reg_names[REGNO (mreg)]);
3033 else if (GET_CODE (reg1) == ZERO_EXTRACT)
3035 fprintf (file, "%s,%slo16(",
3036 reg_names[REGNO (reg0)], m88k_pound_sign);
3037 output_addr_const (file, XEXP (reg1, 0));
3043 fprintf (file, "%s,", reg_names[REGNO (reg0)]);
3044 output_addr_const (file, reg1);
3045 fputs ("#got_rel", file);
3055 if (REGNO (XEXP (addr, 0)) == ARG_POINTER_REGNUM)
3058 fprintf (file, "%s[%s]",
3059 reg_names[0], reg_names[REGNO (XEXP (addr, 0))]);
3063 fprintf (file, "%s,%shi16(", reg_names[0], m88k_pound_sign);
3064 output_addr_const (file, XEXP (addr, 0));
3069 fprintf (file, "%s,%d", reg_names[0], INTVAL (addr));
3073 fprintf (file, "%s,", reg_names[0]);
3074 if (SHORT_ADDRESS_P (addr, temp))
3076 fprintf (file, "%siw16(", m88k_pound_sign);
3077 output_addr_const (file, addr);
3081 output_addr_const (file, addr);
3085 /* Return true if X is an address which needs a temporary register when
3086 reloaded while generating PIC code. */
3089 pic_address_needs_scratch (x)
3092 /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */
3093 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
3094 && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
3095 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
3096 && ! ADD_INT (XEXP (XEXP (x, 0), 1)))