1 /* Subroutines for insn-output.c for Motorola 88000.
2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001 Free Software Foundation, Inc.
4 Contributed by Michael Tiemann (tiemann@mcc.com)
5 Currently maintained by (gcc@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, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
28 #include "hard-reg-set.h"
30 #include "insn-config.h"
31 #include "conditions.h"
33 #include "insn-attr.h"
44 #include "target-def.h"
46 extern int flag_traditional;
47 extern FILE *asm_out_file;
49 const char *m88k_pound_sign = ""; /* Either # for SVR4 or empty for SVR3 */
50 const char *m88k_short_data;
51 const char *m88k_version;
52 char m88k_volatile_code;
54 unsigned m88k_gp_threshold = 0;
55 int m88k_prologue_done = 0; /* Ln directives can now be emitted */
56 int m88k_function_number = 0; /* Counter unique to each function */
57 int m88k_fp_offset = 0; /* offset of frame pointer if used */
58 int m88k_stack_size = 0; /* size of allocated stack (including frame) */
61 rtx m88k_compare_reg; /* cmp output pseudo register */
62 rtx m88k_compare_op0; /* cmpsi operand 0 */
63 rtx m88k_compare_op1; /* cmpsi operand 1 */
65 enum processor_type m88k_cpu; /* target cpu */
67 static void m88k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
68 static void m88k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
69 static void m88k_output_function_end_prologue PARAMS ((FILE *));
70 static void m88k_output_function_begin_epilogue PARAMS ((FILE *));
71 #ifdef INIT_SECTION_ASM_OP
72 static void m88k_svr3_asm_out_constructor PARAMS ((rtx, int));
73 static void m88k_svr3_asm_out_destructor PARAMS ((rtx, int));
76 static int m88k_adjust_cost PARAMS ((rtx, rtx, rtx, int));
78 /* Initialize the GCC target structure. */
79 #undef TARGET_ASM_FUNCTION_PROLOGUE
80 #define TARGET_ASM_FUNCTION_PROLOGUE m88k_output_function_prologue
81 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
82 #define TARGET_ASM_FUNCTION_END_PROLOGUE m88k_output_function_end_prologue
83 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
84 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE m88k_output_function_begin_epilogue
85 #undef TARGET_ASM_FUNCTION_EPILOGUE
86 #define TARGET_ASM_FUNCTION_EPILOGUE m88k_output_function_epilogue
88 #undef TARGET_SCHED_ADJUST_COST
89 #define TARGET_SCHED_ADJUST_COST m88k_adjust_cost
91 struct gcc_target targetm = TARGET_INITIALIZER;
93 /* Determine what instructions are needed to manufacture the integer VALUE
97 classify_integer (mode, value)
98 enum machine_mode mode;
103 else if (SMALL_INTVAL (value))
105 else if (SMALL_INTVAL (-value))
107 else if (mode == HImode)
109 else if (mode == QImode)
111 else if ((value & 0xffff) == 0)
112 return m88k_oru_hi16;
113 else if (integer_ok_for_set (value))
119 /* Return the bit number in a compare word corresponding to CONDITION. */
122 condition_value (condition)
125 switch (GET_CODE (condition))
142 integer_ok_for_set (value)
143 register unsigned value;
145 /* All the "one" bits must be contiguous. If so, MASK + 1 will be
146 a power of two or zero. */
147 register unsigned mask = (value | (value - 1));
148 return (value && POWER_OF_2_or_0 (mask + 1));
152 output_load_const_int (mode, operands)
153 enum machine_mode mode;
156 static const char *const patterns[] =
164 "or.u %0,%#r0,%X1\n\tor %0,%0,%x1",
167 if (! REG_P (operands[0])
168 || GET_CODE (operands[1]) != CONST_INT)
170 return patterns[classify_integer (mode, INTVAL (operands[1]))];
173 /* These next two routines assume that floating point numbers are represented
174 in a manner which is consistent between host and target machines. */
177 output_load_const_float (operands)
180 /* These can return 0 under some circumstances when cross-compiling. */
181 operands[0] = operand_subword (operands[0], 0, 0, SFmode);
182 operands[1] = operand_subword (operands[1], 0, 0, SFmode);
184 return output_load_const_int (SImode, operands);
188 output_load_const_double (operands)
193 /* These can return zero on some cross-compilers, but there's nothing
194 we can do about it. */
195 latehalf[0] = operand_subword (operands[0], 1, 0, DFmode);
196 latehalf[1] = operand_subword (operands[1], 1, 0, DFmode);
198 operands[0] = operand_subword (operands[0], 0, 0, DFmode);
199 operands[1] = operand_subword (operands[1], 0, 0, DFmode);
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);
210 output_load_const_dimode (operands)
215 latehalf[0] = operand_subword (operands[0], 1, 0, DImode);
216 latehalf[1] = operand_subword (operands[1], 1, 0, DImode);
218 operands[0] = operand_subword (operands[0], 0, 0, DImode);
219 operands[1] = operand_subword (operands[1], 0, 0, DImode);
221 output_asm_insn (output_load_const_int (SImode, operands), operands);
223 operands[0] = latehalf[0];
224 operands[1] = latehalf[1];
226 return output_load_const_int (SImode, operands);
229 /* Emit insns to move operands[1] into operands[0].
231 Return 1 if we have written out everything that needs to be done to
232 do the move. Otherwise, return 0 and the caller will emit the move
235 SCRATCH if non zero can be used as a scratch register for the move
236 operation. It is provided by a SECONDARY_RELOAD_* macro if needed. */
239 emit_move_sequence (operands, mode, scratch)
241 enum machine_mode mode;
244 register rtx operand0 = operands[0];
245 register rtx operand1 = operands[1];
247 if (CONSTANT_P (operand1) && flag_pic
248 && pic_address_needs_scratch (operand1))
249 operands[1] = operand1 = legitimize_address (1, operand1, 0, 0);
251 /* Handle most common case first: storing into a register. */
252 if (register_operand (operand0, mode))
254 if (register_operand (operand1, mode)
255 || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
256 || GET_CODE (operand1) == HIGH
257 /* Only `general_operands' can come here, so MEM is ok. */
258 || GET_CODE (operand1) == MEM)
260 /* Run this case quickly. */
261 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
265 else if (GET_CODE (operand0) == MEM)
267 if (register_operand (operand1, mode)
268 || (operand1 == const0_rtx && GET_MODE_SIZE (mode) <= UNITS_PER_WORD))
270 /* Run this case quickly. */
271 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
274 if (! reload_in_progress && ! reload_completed)
276 operands[0] = validize_mem (operand0);
277 operands[1] = operand1 = force_reg (mode, operand1);
281 /* Simplify the source if we need to. */
282 if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
284 if (GET_CODE (operand1) != CONST_INT
285 && GET_CODE (operand1) != CONST_DOUBLE)
287 rtx temp = ((reload_in_progress || reload_completed)
289 operands[1] = legitimize_address (flag_pic
290 && symbolic_address_p (operand1),
291 operand1, temp, scratch);
293 operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
297 /* Now have insn-emit do whatever it normally does. */
301 /* Return a legitimate reference for ORIG (either an address or a MEM)
302 using the register REG. If PIC and the address is already
303 position-independent, use ORIG. Newly generated position-independent
304 addresses go into a reg. This is REG if non zero, otherwise we
305 allocate register(s) as necessary. If this is called during reload,
306 and we need a second temp register, then we use SCRATCH, which is
307 provided via the SECONDARY_INPUT_RELOAD_CLASS mechanism. */
310 legitimize_address (pic, orig, reg, scratch)
316 rtx addr = (GET_CODE (orig) == MEM ? XEXP (orig, 0) : orig);
322 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
326 if (reload_in_progress || reload_completed)
329 reg = gen_reg_rtx (Pmode);
334 /* If not during reload, allocate another temp reg here for
335 loading in the address, so that these instructions can be
336 optimized properly. */
337 temp = ((reload_in_progress || reload_completed)
338 ? reg : gen_reg_rtx (Pmode));
340 emit_insn (gen_rtx_SET
342 gen_rtx_HIGH (SImode,
343 gen_rtx_UNSPEC (SImode,
347 emit_insn (gen_rtx_SET
349 gen_rtx_LO_SUM (SImode, temp,
350 gen_rtx_UNSPEC (SImode,
356 new = gen_rtx_MEM (Pmode,
357 gen_rtx_PLUS (SImode,
358 pic_offset_table_rtx, addr));
360 current_function_uses_pic_offset_table = 1;
361 RTX_UNCHANGING_P (new) = 1;
362 insn = emit_move_insn (reg, new);
363 /* Put a REG_EQUAL note on this insn, so that it can be optimized
365 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
369 else if (GET_CODE (addr) == CONST)
373 if (GET_CODE (XEXP (addr, 0)) == PLUS
374 && XEXP (XEXP (addr, 0), 0) == pic_offset_table_rtx)
379 if (reload_in_progress || reload_completed)
382 reg = gen_reg_rtx (Pmode);
385 if (GET_CODE (XEXP (addr, 0)) != PLUS) abort ();
387 base = legitimize_address (1, XEXP (XEXP (addr, 0), 0), reg, 0);
388 addr = legitimize_address (1, XEXP (XEXP (addr, 0), 1),
389 base == reg ? 0 : reg, 0);
391 if (GET_CODE (addr) == CONST_INT)
394 return plus_constant (base, INTVAL (addr));
395 else if (! reload_in_progress && ! reload_completed)
396 addr = force_reg (Pmode, addr);
397 /* We can't create any new registers during reload, so use the
398 SCRATCH reg provided by the reload_insi pattern. */
401 emit_move_insn (scratch, addr);
405 /* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS
406 macro needs to be adjusted so that a scratch reg is provided
410 new = gen_rtx_PLUS (SImode, base, addr);
411 /* Should we set special REG_NOTEs here? */
414 else if (! SHORT_ADDRESS_P (addr, temp))
418 if (reload_in_progress || reload_completed)
421 reg = gen_reg_rtx (Pmode);
424 emit_insn (gen_rtx_SET (VOIDmode,
425 reg, gen_rtx_HIGH (SImode, addr)));
426 new = gen_rtx_LO_SUM (SImode, reg, addr);
430 && GET_CODE (orig) == MEM)
432 new = gen_rtx_MEM (GET_MODE (orig), new);
433 MEM_COPY_ATTRIBUTES (new, orig);
438 /* Support functions for code to emit a block move. There are four methods
439 used to perform the block move:
441 + call the looping library function, e.g. __movstrSI64n8
442 + call a non-looping library function, e.g. __movstrHI15x11
443 + produce an inline sequence of ld/st instructions
445 The parameters below describe the library functions produced by
448 #define MOVSTR_LOOP 64 /* __movstrSI64n68 .. __movstrSI64n8 */
449 #define MOVSTR_QI 16 /* __movstrQI16x16 .. __movstrQI16x2 */
450 #define MOVSTR_HI 48 /* __movstrHI48x48 .. __movstrHI48x4 */
451 #define MOVSTR_SI 96 /* __movstrSI96x96 .. __movstrSI96x8 */
452 #define MOVSTR_DI 96 /* __movstrDI96x96 .. __movstrDI96x16 */
453 #define MOVSTR_ODD_HI 16 /* __movstrHI15x15 .. __movstrHI15x5 */
454 #define MOVSTR_ODD_SI 48 /* __movstrSI47x47 .. __movstrSI47x11,
455 __movstrSI46x46 .. __movstrSI46x10,
456 __movstrSI45x45 .. __movstrSI45x9 */
457 #define MOVSTR_ODD_DI 48 /* __movstrDI47x47 .. __movstrDI47x23,
458 __movstrDI46x46 .. __movstrDI46x22,
459 __movstrDI45x45 .. __movstrDI45x21,
460 __movstrDI44x44 .. __movstrDI44x20,
461 __movstrDI43x43 .. __movstrDI43x19,
462 __movstrDI42x42 .. __movstrDI42x18,
463 __movstrDI41x41 .. __movstrDI41x17 */
465 /* Limits for using the non-looping movstr functions. For the m88100
466 processor, we assume the source and destination are word aligned.
467 The QImode and HImode limits are the break even points where memcpy
468 does just as well and beyond which memcpy does better. For the
469 m88110, we tend to assume double word alignment, but also analyze
470 the word aligned cases. The analysis is complicated because memcpy
471 may use the cache control instructions for better performance. */
473 #define MOVSTR_QI_LIMIT_88100 13
474 #define MOVSTR_HI_LIMIT_88100 38
475 #define MOVSTR_SI_LIMIT_88100 MOVSTR_SI
476 #define MOVSTR_DI_LIMIT_88100 MOVSTR_SI
478 #define MOVSTR_QI_LIMIT_88000 16
479 #define MOVSTR_HI_LIMIT_88000 38
480 #define MOVSTR_SI_LIMIT_88000 72
481 #define MOVSTR_DI_LIMIT_88000 72
483 #define MOVSTR_QI_LIMIT_88110 16
484 #define MOVSTR_HI_LIMIT_88110 38
485 #define MOVSTR_SI_LIMIT_88110 72
486 #define MOVSTR_DI_LIMIT_88110 72
488 static const enum machine_mode mode_from_align[] =
489 {VOIDmode, QImode, HImode, VOIDmode, SImode,
490 VOIDmode, VOIDmode, VOIDmode, DImode};
491 static const int max_from_align[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI,
493 static const int all_from_align[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0,
494 MOVSTR_ODD_SI, 0, 0, 0, MOVSTR_ODD_DI};
496 static const int best_from_align[3][9] = {
497 {0, MOVSTR_QI_LIMIT_88100, MOVSTR_HI_LIMIT_88100, 0, MOVSTR_SI_LIMIT_88100,
498 0, 0, 0, MOVSTR_DI_LIMIT_88100},
499 {0, MOVSTR_QI_LIMIT_88110, MOVSTR_HI_LIMIT_88110, 0, MOVSTR_SI_LIMIT_88110,
500 0, 0, 0, MOVSTR_DI_LIMIT_88110},
501 {0, MOVSTR_QI_LIMIT_88000, MOVSTR_HI_LIMIT_88000, 0, MOVSTR_SI_LIMIT_88000,
502 0, 0, 0, MOVSTR_DI_LIMIT_88000}
505 static void block_move_loop PARAMS ((rtx, rtx, rtx, rtx, int, int));
506 static void block_move_no_loop PARAMS ((rtx, rtx, rtx, rtx, int, int));
507 static void block_move_sequence PARAMS ((rtx, rtx, rtx, rtx, int, int, int));
508 static void output_short_branch_defs PARAMS ((FILE *));
509 static int output_option PARAMS ((FILE *, const char *, const char *,
510 const char *, const char *, int, int));
512 /* Emit code to perform a block move. Choose the best method.
514 OPERANDS[0] is the destination.
515 OPERANDS[1] is the source.
516 OPERANDS[2] is the size.
517 OPERANDS[3] is the alignment safe to use. */
520 expand_block_move (dest_mem, src_mem, operands)
525 int align = INTVAL (operands[3]);
526 int constp = (GET_CODE (operands[2]) == CONST_INT);
527 int bytes = (constp ? INTVAL (operands[2]) : 0);
528 int target = (int) m88k_cpu;
530 if (! (PROCESSOR_M88100 == 0
531 && PROCESSOR_M88110 == 1
532 && PROCESSOR_M88000 == 2))
535 if (constp && bytes <= 0)
538 /* Determine machine mode to do move with. */
539 if (align > 4 && !TARGET_88110)
541 else if (align <= 0 || align == 3)
542 abort (); /* block move invalid alignment. */
544 if (constp && bytes <= 3 * align)
545 block_move_sequence (operands[0], dest_mem, operands[1], src_mem,
548 else if (constp && bytes <= best_from_align[target][align])
549 block_move_no_loop (operands[0], dest_mem, operands[1], src_mem,
552 else if (constp && align == 4 && TARGET_88100)
553 block_move_loop (operands[0], dest_mem, operands[1], src_mem,
558 #ifdef TARGET_MEM_FUNCTIONS
559 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "memcpy"), 0,
563 convert_to_mode (TYPE_MODE (sizetype), operands[2],
564 TREE_UNSIGNED (sizetype)),
565 TYPE_MODE (sizetype));
567 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "bcopy"), 0,
571 convert_to_mode (TYPE_MODE (integer_type_node),
573 TREE_UNSIGNED (integer_type_node)),
574 TYPE_MODE (integer_type_node));
579 /* Emit code to perform a block move by calling a looping movstr library
580 function. SIZE and ALIGN are known constants. DEST and SRC are
584 block_move_loop (dest, dest_mem, src, src_mem, size, align)
590 enum machine_mode mode;
599 /* Determine machine mode to do move with. */
603 /* Determine the structure of the loop. */
604 count = size / MOVSTR_LOOP;
605 units = (size - count * MOVSTR_LOOP) / align;
610 units += MOVSTR_LOOP / align;
615 block_move_no_loop (dest, dest_mem, src, src_mem, size, align);
619 remainder = size - count * MOVSTR_LOOP - units * align;
621 mode = mode_from_align[align];
622 sprintf (entry, "__movstr%s%dn%d",
623 GET_MODE_NAME (mode), MOVSTR_LOOP, units * align);
624 entry_name = get_identifier (entry);
626 offset_rtx = GEN_INT (MOVSTR_LOOP + (1 - units) * align);
628 value_rtx = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode,
630 gen_rtx_REG (Pmode, 3),
632 MEM_COPY_ATTRIBUTES (value_rtx, src_mem);
634 emit_insn (gen_call_movstrsi_loop
635 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)),
636 dest, src, offset_rtx, value_rtx,
637 gen_rtx_REG (mode, ((units & 1) ? 4 : 5)),
641 block_move_sequence (gen_rtx_REG (Pmode, 2), dest_mem,
642 gen_rtx_REG (Pmode, 3), src_mem,
643 remainder, align, MOVSTR_LOOP + align);
646 /* Emit code to perform a block move by calling a non-looping library
647 function. SIZE and ALIGN are known constants. DEST and SRC are
648 registers. OFFSET is the known starting point for the output pattern. */
651 block_move_no_loop (dest, dest_mem, src, src_mem, size, align)
657 enum machine_mode mode = mode_from_align[align];
658 int units = size / align;
659 int remainder = size - units * align;
667 if (remainder && size <= all_from_align[align])
669 most = all_from_align[align] - (align - remainder);
674 most = max_from_align[align];
677 sprintf (entry, "__movstr%s%dx%d",
678 GET_MODE_NAME (mode), most, size - remainder);
679 entry_name = get_identifier (entry);
681 offset_rtx = GEN_INT (most - (size - remainder));
683 value_rtx = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode,
685 gen_rtx_REG (Pmode, 3),
688 MEM_COPY_ATTRIBUTES (value_rtx, src_mem);
690 value_reg = ((((most - (size - remainder)) / align) & 1) == 0
691 ? (align == 8 ? 6 : 5) : 4);
693 emit_insn (gen_call_block_move
694 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)),
695 dest, src, offset_rtx, value_rtx,
696 gen_rtx_REG (mode, value_reg)));
699 block_move_sequence (gen_rtx_REG (Pmode, 2), dest_mem,
700 gen_rtx_REG (Pmode, 3), src_mem,
701 remainder, align, most);
704 /* Emit code to perform a block move with an offset sequence of ld/st
705 instructions (..., ld 0, st 1, ld 1, st 0, ...). SIZE and ALIGN are
706 known constants. DEST and SRC are registers. OFFSET is the known
707 starting point for the output pattern. */
710 block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset)
718 enum machine_mode mode[2];
723 int offset_ld = offset;
724 int offset_st = offset;
726 active[0] = active[1] = FALSE;
728 /* Establish parameters for the first load and for the second load if
729 it is known to be the same mode as the first. */
730 amount[0] = amount[1] = align;
731 mode[0] = mode_from_align[align];
732 temp[0] = gen_reg_rtx (mode[0]);
733 if (size >= 2 * align)
736 temp[1] = gen_reg_rtx (mode[1]);
747 /* Change modes as the sequence tails off. */
748 if (size < amount[next])
750 amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1));
751 mode[next] = mode_from_align[amount[next]];
752 temp[next] = gen_reg_rtx (mode[next]);
754 size -= amount[next];
755 srcp = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode[next] : BLKmode,
756 plus_constant (src, offset_ld));
758 MEM_COPY_ATTRIBUTES (srcp, src_mem);
759 emit_insn (gen_rtx_SET (VOIDmode, temp[next], srcp));
760 offset_ld += amount[next];
766 active[phase] = FALSE;
768 = gen_rtx_MEM (MEM_IN_STRUCT_P (dest_mem) ? mode[phase] : BLKmode,
769 plus_constant (dest, offset_st));
771 MEM_COPY_ATTRIBUTES (dstp, dest_mem);
772 emit_insn (gen_rtx_SET (VOIDmode, dstp, temp[phase]));
773 offset_st += amount[phase];
776 while (active[next]);
779 /* Emit the code to do an AND operation. */
782 output_and (operands)
787 if (REG_P (operands[2]))
788 return "and %0,%1,%2";
790 value = INTVAL (operands[2]);
791 if (SMALL_INTVAL (value))
792 return "mask %0,%1,%2";
793 else if ((value & 0xffff0000) == 0xffff0000)
794 return "and %0,%1,%x2";
795 else if ((value & 0xffff) == 0xffff)
796 return "and.u %0,%1,%X2";
797 else if ((value & 0xffff) == 0)
798 return "mask.u %0,%1,%X2";
799 else if (integer_ok_for_set (~value))
800 return "clr %0,%1,%S2";
802 return "and.u %0,%1,%X2\n\tand %0,%0,%x2";
805 /* Emit the code to do an inclusive OR operation. */
808 output_ior (operands)
813 if (REG_P (operands[2]))
814 return "or %0,%1,%2";
816 value = INTVAL (operands[2]);
817 if (SMALL_INTVAL (value))
818 return "or %0,%1,%2";
819 else if ((value & 0xffff) == 0)
820 return "or.u %0,%1,%X2";
821 else if (integer_ok_for_set (value))
822 return "set %0,%1,%s2";
824 return "or.u %0,%1,%X2\n\tor %0,%0,%x2";
827 /* Emit the instructions for doing an XOR. */
830 output_xor (operands)
835 if (REG_P (operands[2]))
836 return "xor %0,%1,%2";
838 value = INTVAL (operands[2]);
839 if (SMALL_INTVAL (value))
840 return "xor %0,%1,%2";
841 else if ((value & 0xffff) == 0)
842 return "xor.u %0,%1,%X2";
844 return "xor.u %0,%1,%X2\n\txor %0,%0,%x2";
847 /* Output a call. Normally this is just bsr or jsr, but this also deals with
848 accomplishing a branch after the call by incrementing r1. This requires
849 that various assembler bugs be accommodated. The 4.30 DG/UX assembler
850 requires that forward references not occur when computing the difference of
851 two labels. The [version?] Motorola assembler computes a word difference.
852 No doubt there's more to come!
854 It would seem the same idea could be used to tail call, but in this case,
855 the epilogue will be non-null. */
857 static rtx sb_name = 0;
858 static rtx sb_high = 0;
859 static rtx sb_low = 0;
862 output_call (operands, addr)
872 /* This can be generalized, but there is currently no need. */
873 if (XVECLEN (final_sequence, 0) != 2)
876 /* The address of interior insns is not computed, so use the sequence. */
877 seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
878 jump = XVECEXP (final_sequence, 0, 1);
879 if (GET_CODE (jump) == JUMP_INSN)
883 rtx dest = XEXP (SET_SRC (PATTERN (jump)), 0);
884 int delta = 4 * (INSN_ADDRESSES (INSN_UID (dest))
885 - INSN_ADDRESSES (INSN_UID (seq_insn))
887 #if (MONITOR_GCC & 0x2) /* How often do long branches happen? */
888 if ((unsigned) (delta + 0x8000) >= 0x10000)
889 warning ("Internal gcc monitor: short-branch(%x)", delta);
892 /* Delete the jump. */
893 PUT_CODE (jump, NOTE);
894 NOTE_LINE_NUMBER (jump) = NOTE_INSN_DELETED;
895 NOTE_SOURCE_FILE (jump) = 0;
897 /* We only do this optimization if -O2, modifying the value of
898 r1 in the delay slot confuses debuggers and profilers on some
901 If we loose, we must use the non-delay form. This is unlikely
902 to ever happen. If it becomes a problem, claim that a call
903 has two delay slots and only the second can be filled with
906 The 88110 can lose when a jsr.n r1 is issued and a page fault
907 occurs accessing the delay slot. So don't use jsr.n form when
910 #ifdef AS_BUG_IMMEDIATE_LABEL /* The assembler restricts immediate values. */
912 || ! ADD_INTVAL (delta * 2)
915 || ! ADD_INTVAL (delta)
917 || (REG_P (addr) && REGNO (addr) == 1))
923 ? "bsr %0#plt\n\tbr %l1"
924 : "bsr %0\n\tbr %l1"));
927 /* Output the short branch form. */
928 output_asm_insn ((REG_P (addr)
930 : (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")),
935 ? "subu %#r1,%#r1,.-%l0+4"
936 : "addu %#r1,%#r1,%l0-.-4");
939 operands[0] = gen_label_rtx ();
940 operands[1] = gen_label_rtx ();
945 last = "subu %#r1,%#r1,%l0\n%l1:";
951 last = "addu %#r1,%#r1,%l0\n%l1:";
954 /* Record the values to be computed later as "def name,high-low". */
955 sb_name = gen_rtx_EXPR_LIST (VOIDmode, operands[0], sb_name);
956 sb_high = gen_rtx_EXPR_LIST (VOIDmode, high, sb_high);
957 sb_low = gen_rtx_EXPR_LIST (VOIDmode, low, sb_low);
958 #endif /* Don't USE_GAS */
965 : (flag_pic ? "bsr%. %0#plt" : "bsr%. %0"));
969 output_short_branch_defs (stream)
972 char name[256], high[256], low[256];
974 for (; sb_name && sb_high && sb_low;
975 sb_name = XEXP (sb_name, 1),
976 sb_high = XEXP (sb_high, 1),
977 sb_low = XEXP (sb_low, 1))
979 ASM_GENERATE_INTERNAL_LABEL
980 (name, "L", CODE_LABEL_NUMBER (XEXP (sb_name, 0)));
981 ASM_GENERATE_INTERNAL_LABEL
982 (high, "L", CODE_LABEL_NUMBER (XEXP (sb_high, 0)));
983 ASM_GENERATE_INTERNAL_LABEL
984 (low, "L", CODE_LABEL_NUMBER (XEXP (sb_low, 0)));
985 /* This will change as the assembler requirements become known. */
986 fprintf (stream, "%s%s,%s-%s\n",
987 SET_ASM_OP, &name[1], &high[1], &low[1]);
989 if (sb_name || sb_high || sb_low)
993 /* Return truth value of the statement that this conditional branch is likely
994 to fall through. CONDITION, is the condition that JUMP_INSN is testing. */
997 mostly_false_jump (jump_insn, condition)
998 rtx jump_insn, condition;
1000 rtx target_label = JUMP_LABEL (jump_insn);
1003 /* Much of this isn't computed unless we're optimizing. */
1007 /* Determine if one path or the other leads to a return. */
1008 for (insnt = NEXT_INSN (target_label);
1010 insnt = NEXT_INSN (insnt))
1012 if (GET_CODE (insnt) == JUMP_INSN)
1014 else if (GET_CODE (insnt) == INSN
1015 && GET_CODE (PATTERN (insnt)) == SEQUENCE
1016 && GET_CODE (XVECEXP (PATTERN (insnt), 0, 0)) == JUMP_INSN)
1018 insnt = XVECEXP (PATTERN (insnt), 0, 0);
1023 && (GET_CODE (PATTERN (insnt)) == RETURN
1024 || (GET_CODE (PATTERN (insnt)) == SET
1025 && GET_CODE (SET_SRC (PATTERN (insnt))) == REG
1026 && REGNO (SET_SRC (PATTERN (insnt))) == 1)))
1029 for (insnj = NEXT_INSN (jump_insn);
1031 insnj = NEXT_INSN (insnj))
1033 if (GET_CODE (insnj) == JUMP_INSN)
1035 else if (GET_CODE (insnj) == INSN
1036 && GET_CODE (PATTERN (insnj)) == SEQUENCE
1037 && GET_CODE (XVECEXP (PATTERN (insnj), 0, 0)) == JUMP_INSN)
1039 insnj = XVECEXP (PATTERN (insnj), 0, 0);
1044 && (GET_CODE (PATTERN (insnj)) == RETURN
1045 || (GET_CODE (PATTERN (insnj)) == SET
1046 && GET_CODE (SET_SRC (PATTERN (insnj))) == REG
1047 && REGNO (SET_SRC (PATTERN (insnj))) == 1)))
1050 /* Predict to not return. */
1051 if ((insnt == 0) != (insnj == 0))
1052 return (insnt == 0);
1054 /* Predict loops to loop. */
1055 for (insnt = PREV_INSN (target_label);
1056 insnt && GET_CODE (insnt) == NOTE;
1057 insnt = PREV_INSN (insnt))
1058 if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_END)
1060 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_BEG)
1062 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_CONT)
1065 /* Predict backward branches usually take. */
1067 insnj = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
1070 if (INSN_ADDRESSES (INSN_UID (insnj))
1071 > INSN_ADDRESSES (INSN_UID (target_label)))
1074 /* EQ tests are usually false and NE tests are usually true. Also,
1075 most quantities are positive, so we can make the appropriate guesses
1076 about signed comparisons against zero. Consider unsigned comparisons
1077 to be a range check and assume quantities to be in range. */
1078 switch (GET_CODE (condition))
1081 /* Unconditional branch. */
1090 case GTU: /* Must get casesi right at least. */
1091 if (XEXP (condition, 1) == const0_rtx)
1098 if (XEXP (condition, 1) == const0_rtx)
1108 /* Return true if the operand is a power of two and is a floating
1109 point type (to optimize division by power of two into multiplication). */
1112 real_power_of_2_operand (op, mode)
1114 enum machine_mode mode ATTRIBUTE_UNUSED;
1118 int i[sizeof (REAL_VALUE_TYPE) / sizeof (int)];
1119 struct { /* IEEE double precision format */
1121 unsigned exponent : 11;
1122 unsigned mantissa1 : 20;
1125 struct { /* IEEE double format to quick check */
1126 unsigned sign : 1; /* if it fits in a float */
1127 unsigned exponent1 : 4;
1128 unsigned exponent2 : 7;
1129 unsigned mantissa1 : 20;
1134 if (GET_MODE (op) != DFmode && GET_MODE (op) != SFmode)
1137 if (GET_CODE (op) != CONST_DOUBLE)
1140 u.i[0] = CONST_DOUBLE_LOW (op);
1141 u.i[1] = CONST_DOUBLE_HIGH (op);
1143 if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0 /* not a power of two */
1144 || u.s.exponent == 0 /* constant 0.0 */
1145 || u.s.exponent == 0x7ff /* NAN */
1146 || (u.s2.exponent1 != 0x8 && u.s2.exponent1 != 0x7))
1147 return 0; /* const won't fit in float */
1152 /* Make OP legitimate for mode MODE. Currently this only deals with DFmode
1153 operands, putting them in registers and making CONST_DOUBLE values
1154 SFmode where possible. */
1157 legitimize_operand (op, mode)
1159 enum machine_mode mode;
1163 union real_extract r;
1164 struct { /* IEEE double precision format */
1166 unsigned exponent : 11;
1167 unsigned mantissa1 : 20;
1170 struct { /* IEEE double format to quick check */
1171 unsigned sign : 1; /* if it fits in a float */
1172 unsigned exponent1 : 4;
1173 unsigned exponent2 : 7;
1174 unsigned mantissa1 : 20;
1179 if (GET_CODE (op) == REG || mode != DFmode)
1182 if (GET_CODE (op) == CONST_DOUBLE)
1184 memcpy (&u.r, &CONST_DOUBLE_LOW (op), sizeof u);
1185 if (u.d.exponent != 0x7ff /* NaN */
1186 && u.d.mantissa2 == 0 /* Mantissa fits */
1187 && (u.s.exponent1 == 0x8 || u.s.exponent1 == 0x7) /* Exponent fits */
1188 && (temp = simplify_unary_operation (FLOAT_TRUNCATE, SFmode,
1190 return gen_rtx_FLOAT_EXTEND (mode, force_reg (SFmode, temp));
1192 else if (register_operand (op, mode))
1195 return force_reg (mode, op);
1198 /* Return true if OP is a suitable input for a move insn. */
1201 move_operand (op, mode)
1203 enum machine_mode mode;
1205 if (register_operand (op, mode))
1207 if (GET_CODE (op) == CONST_INT)
1208 return (classify_integer (mode, INTVAL (op)) < m88k_oru_hi16);
1209 if (GET_MODE (op) != mode)
1211 if (GET_CODE (op) == SUBREG)
1212 op = SUBREG_REG (op);
1213 if (GET_CODE (op) != MEM)
1217 if (GET_CODE (op) == LO_SUM)
1218 return (REG_P (XEXP (op, 0))
1219 && symbolic_address_p (XEXP (op, 1)));
1220 return memory_address_p (mode, op);
1223 /* Return true if OP is suitable for a call insn. */
1226 call_address_operand (op, mode)
1228 enum machine_mode mode ATTRIBUTE_UNUSED;
1230 return (REG_P (op) || symbolic_address_p (op));
1233 /* Returns true if OP is either a symbol reference or a sum of a symbol
1234 reference and a constant. */
1237 symbolic_address_p (op)
1240 switch (GET_CODE (op))
1248 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1249 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1250 && GET_CODE (XEXP (op, 1)) == CONST_INT);
1257 /* Return true if OP is a register or const0_rtx. */
1260 reg_or_0_operand (op, mode)
1262 enum machine_mode mode;
1264 return (op == const0_rtx || register_operand (op, mode));
1267 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
1270 arith_operand (op, mode)
1272 enum machine_mode mode;
1274 return (register_operand (op, mode)
1275 || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
1278 /* Return true if OP is a register or 5 bit integer. */
1281 arith5_operand (op, mode)
1283 enum machine_mode mode;
1285 return (register_operand (op, mode)
1286 || (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32));
1290 arith32_operand (op, mode)
1292 enum machine_mode mode;
1294 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
1298 arith64_operand (op, mode)
1300 enum machine_mode mode;
1302 return (register_operand (op, mode)
1303 || GET_CODE (op) == CONST_INT
1304 || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode));
1308 int5_operand (op, mode)
1310 enum machine_mode mode ATTRIBUTE_UNUSED;
1312 return (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32);
1316 int32_operand (op, mode)
1318 enum machine_mode mode ATTRIBUTE_UNUSED;
1320 return (GET_CODE (op) == CONST_INT);
1323 /* Return true if OP is a register or a valid immediate operand for
1327 add_operand (op, mode)
1329 enum machine_mode mode;
1331 return (register_operand (op, mode)
1332 || (GET_CODE (op) == CONST_INT && ADD_INT (op)));
1335 /* Nonzero if this is a bitmask filling the bottom bits, for optimizing and +
1336 shift left combinations into a single mak instruction. */
1342 return (value && POWER_OF_2_or_0 (value + 1));
1346 reg_or_bbx_mask_operand (op, mode)
1348 enum machine_mode mode;
1351 if (register_operand (op, mode))
1353 if (GET_CODE (op) != CONST_INT)
1356 value = INTVAL (op);
1357 if (POWER_OF_2 (value))
1363 /* Return true if OP is valid to use in the context of a floating
1364 point operation. Special case 0.0, since we can use r0. */
1367 real_or_0_operand (op, mode)
1369 enum machine_mode mode;
1371 if (mode != SFmode && mode != DFmode)
1374 return (register_operand (op, mode)
1375 || (GET_CODE (op) == CONST_DOUBLE
1376 && op == CONST0_RTX (mode)));
1379 /* Return true if OP is valid to use in the context of logic arithmetic
1380 on condition codes. */
1383 partial_ccmode_register_operand (op, mode)
1385 enum machine_mode mode ATTRIBUTE_UNUSED;
1387 return register_operand (op, CCmode) || register_operand (op, CCEVENmode);
1390 /* Return true if OP is a relational operator. */
1395 enum machine_mode mode ATTRIBUTE_UNUSED;
1397 switch (GET_CODE (op))
1416 even_relop (op, mode)
1418 enum machine_mode mode ATTRIBUTE_UNUSED;
1420 switch (GET_CODE (op))
1434 odd_relop (op, mode)
1436 enum machine_mode mode ATTRIBUTE_UNUSED;
1438 switch (GET_CODE (op))
1451 /* Return true if OP is a relational operator, and is not an unsigned
1452 relational operator. */
1455 relop_no_unsigned (op, mode)
1457 enum machine_mode mode ATTRIBUTE_UNUSED;
1459 switch (GET_CODE (op))
1467 /* @@ What is this test doing? Why not use `mode'? */
1468 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
1469 || GET_MODE (op) == DImode
1470 || GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_FLOAT
1471 || GET_MODE (XEXP (op, 0)) == DImode
1472 || GET_MODE_CLASS (GET_MODE (XEXP (op, 1))) == MODE_FLOAT
1473 || GET_MODE (XEXP (op, 1)) == DImode)
1481 /* Return true if the code of this rtx pattern is EQ or NE. */
1484 equality_op (op, mode)
1486 enum machine_mode mode ATTRIBUTE_UNUSED;
1488 return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
1491 /* Return true if the code of this rtx pattern is pc or label_ref. */
1494 pc_or_label_ref (op, mode)
1496 enum machine_mode mode ATTRIBUTE_UNUSED;
1498 return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF);
1501 /* Output to FILE the start of the assembler file. */
1503 /* This definition must match lang_independent_options from toplev.c. */
1504 struct m88k_lang_independent_options
1509 const char *description;
1512 static void output_options PARAMS ((FILE *,
1513 struct m88k_lang_independent_options *,
1515 struct m88k_lang_independent_options *,
1516 int, int, int, const char *, const char *,
1520 output_option (file, sep, type, name, indent, pos, max)
1529 if ((long)(strlen (sep) + strlen (type) + strlen (name) + pos) > max)
1531 fprintf (file, indent);
1532 return fprintf (file, "%s%s", type, name);
1534 return pos + fprintf (file, "%s%s%s", sep, type, name);
1537 static const struct { const char *const name; const int value; } m_options[] =
1541 output_options (file, f_options, f_len, W_options, W_len,
1542 pos, max, sep, indent, term)
1544 struct m88k_lang_independent_options *f_options;
1545 struct m88k_lang_independent_options *W_options;
1556 pos = output_option (file, sep, "-O", "", indent, pos, max);
1557 if (write_symbols != NO_DEBUG)
1558 pos = output_option (file, sep, "-g", "", indent, pos, max);
1559 if (flag_traditional)
1560 pos = output_option (file, sep, "-traditional", "", indent, pos, max);
1562 pos = output_option (file, sep, "-p", "", indent, pos, max);
1563 if (profile_block_flag)
1564 pos = output_option (file, sep, "-a", "", indent, pos, max);
1566 for (j = 0; j < f_len; j++)
1567 if (*f_options[j].variable == f_options[j].on_value)
1568 pos = output_option (file, sep, "-f", f_options[j].string,
1571 for (j = 0; j < W_len; j++)
1572 if (*W_options[j].variable == W_options[j].on_value)
1573 pos = output_option (file, sep, "-W", W_options[j].string,
1576 for (j = 0; j < (long) ARRAY_SIZE (m_options); j++)
1577 if (m_options[j].name[0] != '\0'
1578 && m_options[j].value > 0
1579 && ((m_options[j].value & target_flags)
1580 == m_options[j].value))
1581 pos = output_option (file, sep, "-m", m_options[j].name,
1584 if (m88k_short_data)
1585 pos = output_option (file, sep, "-mshort-data-", m88k_short_data,
1588 fprintf (file, term);
1592 output_file_start (file, f_options, f_len, W_options, W_len)
1594 struct m88k_lang_independent_options *f_options;
1595 struct m88k_lang_independent_options *W_options;
1600 ASM_FIRST_LINE (file);
1603 fprintf (file, "%s\n", REQUIRES_88110_ASM_OP);
1604 output_file_directive (file, main_input_filename);
1605 /* Switch to the data section so that the coffsem symbol
1606 isn't in the text section. */
1609 if (TARGET_IDENTIFY_REVISION)
1613 time_t now = time ((time_t *)0);
1614 sprintf (indent, "]\"\n%s\"@(#)%s [", IDENT_ASM_OP, main_input_filename);
1615 fprintf (file, indent+3);
1616 pos = fprintf (file, "gcc %s, %.24s,", version_string, ctime (&now));
1618 /* ??? It would be nice to call print_switch_values here (and thereby
1619 let us delete output_options) but this is kept in until it is known
1620 whether the change in content format matters. */
1621 output_options (file, f_options, f_len, W_options, W_len,
1622 pos, 150 - strlen (indent), " ", indent, "]\"\n\n");
1624 fprintf (file, "]\"\n");
1625 print_switch_values (file, 0, 150 - strlen (indent),
1626 indent + 3, " ", "]\"\n");
1631 /* Output an ascii string. */
1634 output_ascii (file, opcode, max, p, size)
1644 register int num = 0;
1646 fprintf (file, "%s\"", opcode);
1647 for (i = 0; i < size; i++)
1649 register int c = (unsigned char) p[i];
1653 fprintf (file, "\"\n%s\"", opcode);
1657 if (c == '\"' || c == '\\')
1665 else if (in_escape && c >= '0' && c <= '9')
1667 /* If a digit follows an octal-escape, the VAX assembler fails
1668 to stop reading the escape after three digits. Continue to
1669 output the values as an octal-escape until a non-digit is
1671 fprintf (file, "\\%03o", c);
1674 else if ((c >= ' ' && c < 0177) || (c == '\t'))
1684 /* Some assemblers can't handle \a, \v, or \?. */
1685 case '\f': c = 'f'; goto escape;
1686 case '\b': c = 'b'; goto escape;
1687 case '\r': c = 'r'; goto escape;
1688 case '\n': c = 'n'; goto escape;
1691 fprintf (file, "\\%03o", c);
1696 fprintf (file, "\"\n");
1699 /* Output a label (allows insn-output.c to be compiled without including
1700 m88k.c or needing to include stdio.h). */
1703 output_label (label_number)
1706 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", label_number);
1709 /* Generate the assembly code for function entry.
1711 The prologue is responsible for setting up the stack frame,
1712 initializing the frame pointer register, saving registers that must be
1713 saved, and allocating SIZE additional bytes of storage for the
1714 local variables. SIZE is an integer. FILE is a stdio
1715 stream to which the assembler code should be output.
1717 The label for the beginning of the function need not be output by this
1718 macro. That has already been done when the macro is run.
1720 To determine which registers to save, the macro can refer to the array
1721 `regs_ever_live': element R is nonzero if hard register
1722 R is used anywhere within the function. This implies the
1723 function prologue should save register R, but not if it is one
1724 of the call-used registers.
1726 On machines where functions may or may not have frame-pointers, the
1727 function entry code must vary accordingly; it must set up the frame
1728 pointer if one is wanted, and not otherwise. To determine whether a
1729 frame pointer is in wanted, the macro can refer to the variable
1730 `frame_pointer_needed'. The variable's value will be 1 at run
1731 time in a function that needs a frame pointer.
1733 On machines where an argument may be passed partly in registers and
1734 partly in memory, this macro must examine the variable
1735 `current_function_pretend_args_size', and allocate that many bytes
1736 of uninitialized space on the stack just underneath the first argument
1737 arriving on the stack. (This may not be at the very end of the stack,
1738 if the calling sequence has pushed anything else since pushing the stack
1739 arguments. But usually, on such machines, nothing else has been pushed
1740 yet, because the function prologue itself does all the pushing.)
1742 If `ACCUMULATE_OUTGOING_ARGS' is defined, the variable
1743 `current_function_outgoing_args_size' contains the size in bytes
1744 required for the outgoing arguments. This macro must add that
1745 amount of uninitialized space to very bottom of the stack.
1747 The stack frame we use looks like this:
1750 |==============================================|
1752 |==============================================|
1753 | [caller's outgoing memory arguments] |
1754 |==============================================|
1755 | caller's outgoing argument area (32 bytes) |
1756 sp -> |==============================================| <- ap
1757 | [local variable space] |
1758 |----------------------------------------------|
1759 | [return address (r1)] |
1760 |----------------------------------------------|
1761 | [previous frame pointer (r30)] |
1762 |==============================================| <- fp
1763 | [preserved registers (r25..r14)] |
1764 |----------------------------------------------|
1765 | [preserved registers (x29..x22)] |
1766 |==============================================|
1767 | [dynamically allocated space (alloca)] |
1768 |==============================================|
1769 | [callee's outgoing memory arguments] |
1770 |==============================================|
1771 | [callee's outgoing argument area (32 bytes)] |
1772 |==============================================| <- sp
1776 r1 and r30 must be saved if debugging.
1778 fp (if present) is located two words down from the local
1782 static void emit_add PARAMS ((rtx, rtx, int));
1783 static void preserve_registers PARAMS ((int, int));
1784 static void emit_ldst PARAMS ((int, int, enum machine_mode, int));
1785 static void output_tdesc PARAMS ((FILE *, int));
1786 static int uses_arg_area_p PARAMS ((void));
1790 static char save_regs[FIRST_PSEUDO_REGISTER];
1791 static int frame_laid_out;
1792 static int frame_size;
1793 static int variable_args_p;
1794 static int epilogue_marked;
1795 static int prologue_marked;
1797 #define FIRST_OCS_PRESERVE_REGISTER 14
1798 #define LAST_OCS_PRESERVE_REGISTER 30
1800 #define FIRST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 22)
1801 #define LAST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 31)
1803 #define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
1804 #define ROUND_CALL_BLOCK_SIZE(BYTES) \
1805 (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
1807 /* Establish the position of the FP relative to the SP. This is done
1808 either during output_function_prologue() or by
1809 INITIAL_ELIMINATION_OFFSET. */
1812 m88k_layout_frame ()
1818 memset ((char *) &save_regs[0], 0, sizeof (save_regs));
1819 sp_size = nregs = nxregs = 0;
1820 frame_size = get_frame_size ();
1822 /* Since profiling requires a call, make sure r1 is saved. */
1823 if (profile_flag || profile_block_flag)
1826 /* If we are producing debug information, store r1 and r30 where the
1827 debugger wants to find them (r30 at r30+0, r1 at r30+4). Space has
1828 already been reserved for r1/r30 in STARTING_FRAME_OFFSET. */
1829 if (write_symbols != NO_DEBUG && !TARGET_OCS_FRAME_POSITION)
1832 /* If there is a call, alloca is used, __builtin_alloca is used, or
1833 a dynamic-sized object is defined, add the 8 additional words
1834 for the callee's argument area. The common denominator is that the
1835 FP is required. may_call_alloca only gets calls to alloca;
1836 current_function_calls_alloca gets alloca and __builtin_alloca. */
1837 if (regs_ever_live[1] || frame_pointer_needed)
1840 sp_size += REG_PARM_STACK_SPACE (0);
1843 /* If we are producing PIC, save the addressing base register and r1. */
1844 if (flag_pic && current_function_uses_pic_offset_table)
1846 save_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
1850 /* If a frame is requested, save the previous FP, and the return
1851 address (r1), so that a traceback can be done without using tdesc
1852 information. Otherwise, simply save the FP if it is used as
1853 a preserve register. */
1854 if (frame_pointer_needed)
1855 save_regs[FRAME_POINTER_REGNUM] = save_regs[1] = 1;
1856 else if (regs_ever_live[FRAME_POINTER_REGNUM])
1857 save_regs[FRAME_POINTER_REGNUM] = 1;
1859 /* Figure out which extended register(s) needs to be saved. */
1860 for (regno = FIRST_EXTENDED_REGISTER + 1; regno < FIRST_PSEUDO_REGISTER;
1862 if (regs_ever_live[regno] && ! call_used_regs[regno])
1864 save_regs[regno] = 1;
1868 /* Figure out which normal register(s) needs to be saved. */
1869 for (regno = 2; regno < FRAME_POINTER_REGNUM; regno++)
1870 if (regs_ever_live[regno] && ! call_used_regs[regno])
1872 save_regs[regno] = 1;
1876 /* Achieve greatest use of double memory ops. Either we end up saving
1877 r30 or we use that slot to align the registers we do save. */
1878 if (nregs >= 2 && save_regs[1] && !save_regs[FRAME_POINTER_REGNUM])
1881 nregs += save_regs[1] + save_regs[FRAME_POINTER_REGNUM];
1882 /* if we need to align extended registers, add a word */
1883 if (nxregs > 0 && (nregs & 1) != 0)
1885 sp_size += 4 * nregs;
1886 sp_size += 8 * nxregs;
1887 sp_size += current_function_outgoing_args_size;
1889 /* The first two saved registers are placed above the new frame pointer
1890 if any. In the only case this matters, they are r1 and r30. */
1891 if (frame_pointer_needed || sp_size)
1892 m88k_fp_offset = ROUND_CALL_BLOCK_SIZE (sp_size - STARTING_FRAME_OFFSET);
1894 m88k_fp_offset = -STARTING_FRAME_OFFSET;
1895 m88k_stack_size = m88k_fp_offset + STARTING_FRAME_OFFSET;
1897 /* First, combine m88k_stack_size and size. If m88k_stack_size is
1898 non-zero, align the frame size to 8 mod 16; otherwise align the
1899 frame size to 0 mod 16. (If stacks are 8 byte aligned, this ends
1903 = ((m88k_stack_size ? STACK_UNIT_BOUNDARY - STARTING_FRAME_OFFSET : 0)
1904 - (frame_size % STACK_UNIT_BOUNDARY));
1906 need += STACK_UNIT_BOUNDARY;
1908 = ROUND_CALL_BLOCK_SIZE (m88k_stack_size + frame_size + need
1909 + current_function_pretend_args_size);
1913 /* Return true if this function is known to have a null prologue. */
1918 if (! reload_completed)
1920 if (! frame_laid_out)
1921 m88k_layout_frame ();
1922 return (! frame_pointer_needed
1925 && m88k_stack_size == 0);
1928 /* Determine if the current function has any references to the arg pointer.
1929 This is done indirectly by examining the DECL_ARGUMENTS' DECL_RTL.
1930 It is OK to return TRUE if there are no references, but FALSE must be
1938 if (current_function_decl == 0
1939 || current_function_varargs
1943 for (parm = DECL_ARGUMENTS (current_function_decl);
1945 parm = TREE_CHAIN (parm))
1947 if (DECL_RTL (parm) == 0
1948 || GET_CODE (DECL_RTL (parm)) == MEM)
1951 if (DECL_INCOMING_RTL (parm) == 0
1952 || GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
1959 m88k_output_function_prologue (stream, size)
1960 FILE *stream ATTRIBUTE_UNUSED;
1961 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
1963 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! quiet_flag && leaf_function_p ())
1964 fprintf (stderr, "$");
1966 m88k_prologue_done = 1; /* it's ok now to put out ln directives */
1970 m88k_output_function_end_prologue (stream)
1973 if (TARGET_OCS_DEBUG_INFO && !prologue_marked)
1975 PUT_OCS_FUNCTION_START (stream);
1976 prologue_marked = 1;
1978 /* If we've already passed the start of the epilogue, say that
1979 it starts here. This marks the function as having a null body,
1980 but at a point where the return address is in a known location.
1982 Originally, I thought this couldn't happen, but the pic prologue
1983 for leaf functions ends with the instruction that restores the
1984 return address from the temporary register. If the temporary
1985 register is never used, that instruction can float all the way
1986 to the end of the function. */
1987 if (epilogue_marked)
1988 PUT_OCS_FUNCTION_END (stream);
1993 m88k_expand_prologue ()
1995 m88k_layout_frame ();
1997 if (TARGET_OPTIMIZE_ARG_AREA
1999 && ! uses_arg_area_p ())
2001 /* The incoming argument area is used for stack space if it is not
2002 used (or if -mno-optimize-arg-area is given). */
2003 if ((m88k_stack_size -= REG_PARM_STACK_SPACE (0)) < 0)
2004 m88k_stack_size = 0;
2007 if (m88k_stack_size)
2008 emit_add (stack_pointer_rtx, stack_pointer_rtx, -m88k_stack_size);
2010 if (nregs || nxregs)
2011 preserve_registers (m88k_fp_offset + 4, 1);
2013 if (frame_pointer_needed)
2014 emit_add (frame_pointer_rtx, stack_pointer_rtx, m88k_fp_offset);
2016 if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM])
2018 rtx return_reg = gen_rtx_REG (SImode, 1);
2019 rtx label = gen_label_rtx ();
2024 temp_reg = gen_rtx_REG (SImode, TEMP_REGNUM);
2025 emit_move_insn (temp_reg, return_reg);
2027 emit_insn (gen_locate1 (pic_offset_table_rtx, label));
2028 emit_insn (gen_locate2 (pic_offset_table_rtx, label));
2029 emit_insn (gen_addsi3 (pic_offset_table_rtx,
2030 pic_offset_table_rtx, return_reg));
2032 emit_move_insn (return_reg, temp_reg);
2034 if (profile_flag || profile_block_flag)
2035 emit_insn (gen_blockage ());
2038 /* This function generates the assembly code for function exit,
2039 on machines that need it.
2041 The function epilogue should not depend on the current stack pointer!
2042 It should use the frame pointer only, if there is a frame pointer.
2043 This is mandatory because of alloca; we also take advantage of it to
2044 omit stack adjustments before returning. */
2047 m88k_output_function_begin_epilogue (stream)
2050 if (TARGET_OCS_DEBUG_INFO && !epilogue_marked && prologue_marked)
2052 PUT_OCS_FUNCTION_END (stream);
2054 epilogue_marked = 1;
2058 m88k_output_function_epilogue (stream, size)
2060 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
2062 rtx insn = get_last_insn ();
2064 if (TARGET_OCS_DEBUG_INFO && !epilogue_marked)
2065 PUT_OCS_FUNCTION_END (stream);
2067 /* If the last insn isn't a BARRIER, we must write a return insn. This
2068 should only happen if the function has no prologue and no body. */
2069 if (GET_CODE (insn) == NOTE)
2070 insn = prev_nonnote_insn (insn);
2071 if (insn == 0 || GET_CODE (insn) != BARRIER)
2072 fprintf (stream, "\tjmp\t %s\n", reg_names[1]);
2074 /* If the last insn is a barrier, and the insn before that is a call,
2075 then add a nop instruction so that tdesc can walk the stack correctly
2076 even though there is no epilogue. (Otherwise, the label for the
2077 end of the tdesc region ends up at the start of the next function. */
2078 if (insn && GET_CODE (insn) == BARRIER)
2080 insn = prev_nonnote_insn (insn);
2081 if (insn && GET_CODE (insn) == CALL_INSN)
2082 fprintf (stream, "\tor\t %s,%s,%s\n",reg_names[0],reg_names[0],reg_names[0]);
2085 output_short_branch_defs (stream);
2087 fprintf (stream, "\n");
2089 if (TARGET_OCS_DEBUG_INFO)
2090 output_tdesc (stream, m88k_fp_offset + 4);
2092 m88k_function_number++;
2093 m88k_prologue_done = 0; /* don't put out ln directives */
2094 variable_args_p = 0; /* has variable args */
2096 epilogue_marked = 0;
2097 prologue_marked = 0;
2101 m88k_expand_epilogue ()
2103 #if (MONITOR_GCC & 0x4) /* What are interesting prologue/epilogue values? */
2104 fprintf (stream, "; size = %d, m88k_fp_offset = %d, m88k_stack_size = %d\n",
2105 size, m88k_fp_offset, m88k_stack_size);
2108 if (frame_pointer_needed)
2109 emit_add (stack_pointer_rtx, frame_pointer_rtx, -m88k_fp_offset);
2111 if (nregs || nxregs)
2112 preserve_registers (m88k_fp_offset + 4, 0);
2114 if (m88k_stack_size)
2115 emit_add (stack_pointer_rtx, stack_pointer_rtx, m88k_stack_size);
2118 /* Emit insns to set DSTREG to SRCREG + AMOUNT during the prologue or
2122 emit_add (dstreg, srcreg, amount)
2127 rtx incr = GEN_INT (abs (amount));
2129 if (! ADD_INTVAL (amount))
2131 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
2132 emit_move_insn (temp, incr);
2135 emit_insn ((amount < 0 ? gen_subsi3 : gen_addsi3) (dstreg, srcreg, incr));
2138 /* Save/restore the preserve registers. base is the highest offset from
2139 r31 at which a register is stored. store_p is true if stores are to
2140 be done; otherwise loads. */
2143 preserve_registers (base, store_p)
2152 } mem_op[FIRST_PSEUDO_REGISTER];
2153 struct mem_op *mo_ptr = mem_op;
2155 /* The 88open OCS mandates that preserved registers be stored in
2156 increasing order. For compatibility with current practice,
2157 the order is r1, r30, then the preserve registers. */
2162 /* An extra word is given in this case to make best use of double
2164 if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM])
2166 emit_ldst (store_p, 1, SImode, offset);
2171 /* Walk the registers to save recording all single memory operations. */
2172 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2173 if (save_regs[regno])
2175 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2178 mo_ptr->regno = regno;
2179 mo_ptr->offset = offset;
2190 /* Walk the registers to save recording all double memory operations.
2191 This avoids a delay in the epilogue (ld.d/ld). */
2193 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2194 if (save_regs[regno])
2196 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2203 mo_ptr->regno = regno-1;
2204 mo_ptr->offset = offset-4;
2211 /* Walk the extended registers to record all memory operations. */
2212 /* Be sure the offset is double word aligned. */
2213 offset = (offset - 1) & ~7;
2214 for (regno = FIRST_PSEUDO_REGISTER - 1; regno > FIRST_EXTENDED_REGISTER;
2216 if (save_regs[regno])
2219 mo_ptr->regno = regno;
2220 mo_ptr->offset = offset;
2227 /* Output the memory operations. */
2228 for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++)
2231 emit_ldst (store_p, mo_ptr->regno,
2232 (mo_ptr->nregs > 1 ? DImode : SImode),
2238 emit_ldst (store_p, regno, mode, offset)
2241 enum machine_mode mode;
2244 rtx reg = gen_rtx_REG (mode, regno);
2247 if (SMALL_INTVAL (offset))
2249 mem = gen_rtx_MEM (mode, plus_constant (stack_pointer_rtx, offset));
2253 /* offset is too large for immediate index must use register */
2255 rtx disp = GEN_INT (offset);
2256 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
2257 rtx regi = gen_rtx_PLUS (SImode, stack_pointer_rtx, temp);
2259 emit_move_insn (temp, disp);
2260 mem = gen_rtx_MEM (mode, regi);
2264 emit_move_insn (mem, reg);
2266 emit_move_insn (reg, mem);
2269 /* Convert the address expression REG to a CFA offset. */
2272 m88k_debugger_offset (reg, offset)
2274 register int offset;
2276 if (GET_CODE (reg) == PLUS)
2278 offset = INTVAL (XEXP (reg, 1));
2279 reg = XEXP (reg, 0);
2282 /* Put the offset in terms of the CFA (arg pointer). */
2283 if (reg == frame_pointer_rtx)
2284 offset += m88k_fp_offset - m88k_stack_size;
2285 else if (reg == stack_pointer_rtx)
2286 offset -= m88k_stack_size;
2287 else if (reg != arg_pointer_rtx)
2289 #if (MONITOR_GCC & 0x10) /* Watch for suspicious symbolic locations. */
2290 if (! (GET_CODE (reg) == REG
2291 && REGNO (reg) >= FIRST_PSEUDO_REGISTER))
2292 warning ("Internal gcc error: Can't express symbolic location");
2300 /* Output the 88open OCS proscribed text description information.
2303 0 22: info-byte-length (16 or 20 bytes)
2304 0 2: info-alignment (word 2)
2305 1 32: info-protocol (version 1 or 2(pic))
2306 2 32: starting-address (inclusive, not counting prologue)
2307 3 32: ending-address (exclusive, not counting epilog)
2308 4 8: info-variant (version 1 or 3(extended registers))
2309 4 17: register-save-mask (from register 14 to 30)
2311 4 1: return-address-info-discriminant
2312 4 5: frame-address-register
2313 5 32: frame-address-offset
2314 6 32: return-address-info
2315 7 32: register-save-offset
2316 8 16: extended-register-save-mask (x16 - x31)
2317 8 16: extended-register-save-offset (WORDS from register-save-offset) */
2320 output_tdesc (file, offset)
2325 long mask, return_address_info, register_save_offset;
2326 long xmask, xregister_save_offset;
2329 for (mask = 0, i = 0, regno = FIRST_OCS_PRESERVE_REGISTER;
2330 regno <= LAST_OCS_PRESERVE_REGISTER;
2334 if (save_regs[regno])
2341 for (xmask = 0, j = 0, regno = FIRST_OCS_EXTENDED_PRESERVE_REGISTER;
2342 regno <= LAST_OCS_EXTENDED_PRESERVE_REGISTER;
2346 if (save_regs[regno])
2355 if ((nxregs > 0 || nregs > 2) && !save_regs[FRAME_POINTER_REGNUM])
2357 return_address_info = - m88k_stack_size + offset;
2358 register_save_offset = return_address_info - i*4;
2362 return_address_info = 1;
2363 register_save_offset = - m88k_stack_size + offset + 4 - i*4;
2366 xregister_save_offset = - (j * 2 + ((register_save_offset >> 2) & 1));
2370 fprintf (file, "%s%d,%d", INT_ASM_OP, /* 8:0,22:(20 or 16),2:2 */
2371 (((xmask != 0) ? 20 : 16) << 2) | 2,
2374 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_START_PREFIX, m88k_function_number);
2375 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2376 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_END_PREFIX, m88k_function_number);
2377 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2379 fprintf (file, ",0x%x,0x%x,0x%lx,0x%lx",
2380 /* 8:1,17:0x%.3x,1:0,1:%d,5:%d */
2381 (int)(((xmask ? 3 : 1) << (17+1+1+5))
2383 | ((!!save_regs[1]) << 5)
2384 | (frame_pointer_needed
2385 ? FRAME_POINTER_REGNUM
2386 : STACK_POINTER_REGNUM)),
2387 (m88k_stack_size - (frame_pointer_needed ? m88k_fp_offset : 0)),
2388 return_address_info,
2389 register_save_offset);
2391 fprintf (file, ",0x%lx%04lx", xmask, (0xffff & xregister_save_offset));
2397 /* Output assembler code to FILE to increment profiler label # LABELNO
2398 for profiling a function entry. NAME is the mcount function name
2399 (varies), SAVEP indicates whether the parameter registers need to
2400 be saved and restored. */
2403 output_function_profiler (file, labelno, name, savep)
2411 const char *const temp = (savep ? reg_names[2] : reg_names[10]);
2413 /* Remember to update FUNCTION_PROFILER_LENGTH. */
2417 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2418 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2419 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2420 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2421 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2424 ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno);
2427 fprintf (file, "\tor.u\t %s,%s,%shi16(%s#got_rel)\n",
2428 temp, reg_names[0], m88k_pound_sign, &label[1]);
2429 fprintf (file, "\tor\t %s,%s,%slo16(%s#got_rel)\n",
2430 temp, temp, m88k_pound_sign, &label[1]);
2431 sprintf (dbi, "\tld\t %s,%s,%s\n", temp,
2432 reg_names[PIC_OFFSET_TABLE_REGNUM], temp);
2436 sprintf (dbi, "\tld\t %s,%s,%s#got_rel\n", temp,
2437 reg_names[PIC_OFFSET_TABLE_REGNUM], &label[1]);
2441 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n",
2442 temp, reg_names[0], m88k_pound_sign, &label[1]);
2443 sprintf (dbi, "\tor\t %s,%s,%slo16(%s)\n",
2444 temp, temp, m88k_pound_sign, &label[1]);
2448 fprintf (file, "\tbsr.n\t %s#plt\n", name);
2450 fprintf (file, "\tbsr.n\t %s\n", name);
2455 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2456 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2457 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2458 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2459 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2463 /* Output assembler code to FILE to initialize basic-block profiling for
2464 the current module. LABELNO is unique to each instance. */
2467 output_function_block_profiler (file, labelno)
2474 /* Remember to update FUNCTION_BLOCK_PROFILER_LENGTH. */
2476 ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 0);
2477 ASM_GENERATE_INTERNAL_LABEL (label, "LPY", labelno);
2479 /* @@ Need to deal with PIC. I'm not sure what the requirements are on
2480 register usage, so I used r26/r27 to be safe. */
2481 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n", reg_names[27], reg_names[0],
2482 m88k_pound_sign, &block[1]);
2483 fprintf (file, "\tld\t %s,%s,%slo16(%s)\n", reg_names[26], reg_names[27],
2484 m88k_pound_sign, &block[1]);
2485 fprintf (file, "\tbcnd\t %sne0,%s,%s\n",
2486 m88k_pound_sign, reg_names[26], &label[1]);
2487 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2488 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2489 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2490 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2491 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2492 fputs ("\tbsr.n\t ", file);
2493 ASM_OUTPUT_LABELREF (file, "__bb_init_func");
2495 fprintf (file, "\tor\t %s,%s,%slo16(%s)\n", reg_names[2], reg_names[27],
2496 m88k_pound_sign, &block[1]);
2497 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2498 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2499 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2500 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2501 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2502 ASM_OUTPUT_INTERNAL_LABEL (file, "LPY", labelno);
2505 /* Output assembler code to FILE to increment the count associated with
2506 the basic block number BLOCKNO. */
2509 output_block_profiler (file, blockno)
2515 /* Remember to update BLOCK_PROFILER_LENGTH. */
2517 ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 2);
2519 /* @@ Need to deal with PIC. I'm not sure what the requirements are on
2520 register usage, so I used r26/r27 to be safe. */
2521 fprintf (file, "\tor.u\t %s,%s,%shi16(%s+%d)\n", reg_names[27], reg_names[0],
2522 m88k_pound_sign, &block[1], 4 * blockno);
2523 fprintf (file, "\tld\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27],
2524 m88k_pound_sign, &block[1], 4 * blockno);
2525 fprintf (file, "\taddu\t %s,%s,1\n", reg_names[26], reg_names[26]);
2526 fprintf (file, "\tst\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27],
2527 m88k_pound_sign, &block[1], 4 * blockno);
2530 /* Determine whether a function argument is passed in a register, and
2533 The arguments are CUM, which summarizes all the previous
2534 arguments; MODE, the machine mode of the argument; TYPE,
2535 the data type of the argument as a tree node or 0 if that is not known
2536 (which happens for C support library functions); and NAMED,
2537 which is 1 for an ordinary argument and 0 for nameless arguments that
2538 correspond to `...' in the called function's prototype.
2540 The value of the expression should either be a `reg' RTX for the
2541 hard register in which to pass the argument, or zero to pass the
2542 argument on the stack.
2544 On the m88000 the first eight words of args are normally in registers
2545 and the rest are pushed. Double precision floating point must be
2546 double word aligned (and if in a register, starting on an even
2547 register). Structures and unions which are not 4 byte, and word
2548 aligned are passed in memory rather than registers, even if they
2549 would fit completely in the registers under OCS rules.
2551 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2552 For structures that are passed in memory, but could have been
2553 passed in registers, we first load the structure into the
2554 register, and then when the last argument is passed, we store
2555 the registers into the stack locations. This fixes some bugs
2556 where GCC did not expect to have register arguments, followed
2557 by stack arguments, followed by register arguments. */
2560 m88k_function_arg (args_so_far, mode, type, named)
2561 CUMULATIVE_ARGS args_so_far;
2562 enum machine_mode mode;
2564 int named ATTRIBUTE_UNUSED;
2568 if (type != 0 /* undo putting struct in register */
2569 && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
2572 if (mode == BLKmode && TARGET_WARN_PASS_STRUCT)
2573 warning ("argument #%d is a structure", args_so_far + 1);
2575 if ((args_so_far & 1) != 0
2576 && (mode == DImode || mode == DFmode
2577 || (type != 0 && TYPE_ALIGN (type) > 32)))
2582 return (rtx) 0; /* don't put args in registers */
2585 if (type == 0 && mode == BLKmode)
2586 abort (); /* m88k_function_arg argument `type' is NULL for BLKmode. */
2588 bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
2589 words = (bytes + 3) / 4;
2591 if (args_so_far + words > 8)
2592 return (rtx) 0; /* args have exhausted registers */
2594 else if (mode == BLKmode
2595 && (TYPE_ALIGN (type) != BITS_PER_WORD
2596 || bytes != UNITS_PER_WORD))
2599 return gen_rtx_REG (((mode == BLKmode) ? TYPE_MODE (type) : mode),
2603 /* Do what is necessary for `va_start'. We look at the current function
2604 to determine if stdargs or varargs is used and spill as necessary.
2605 We return a pointer to the spill area. */
2608 m88k_builtin_saveregs ()
2611 tree fntype = TREE_TYPE (current_function_decl);
2612 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2613 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2614 != void_type_node)))
2615 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
2618 variable_args_p = 1;
2621 if (GET_CODE (current_function_arg_offset_rtx) == CONST_INT)
2622 fixed = ((INTVAL (current_function_arg_offset_rtx) + argadj)
2625 /* Allocate the register space, and store it as the __va_reg member. */
2626 addr = assign_stack_local (BLKmode, 8 * UNITS_PER_WORD, -1);
2627 set_mem_alias_set (addr, get_varargs_alias_set ());
2628 RTX_UNCHANGING_P (addr) = 1;
2629 RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
2631 /* Now store the incoming registers. */
2634 dest = adjust_address (addr, Pmode, fixed * UNITS_PER_WORD);
2635 move_block_from_reg (2 + fixed, dest, 8 - fixed,
2636 UNITS_PER_WORD * (8 - fixed));
2638 if (current_function_check_memory_usage)
2640 emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
2642 GEN_INT (UNITS_PER_WORD * (8 - fixed)),
2643 TYPE_MODE (sizetype),
2644 GEN_INT (MEMORY_USE_RW),
2645 TYPE_MODE (integer_type_node));
2649 /* Return the address of the save area, but don't put it in a
2650 register. This fails when not optimizing and produces worse code
2652 return XEXP (addr, 0);
2655 /* Define the `__builtin_va_list' type for the ABI. */
2658 m88k_build_va_list ()
2660 tree field_reg, field_stk, field_arg, int_ptr_type_node, record;
2662 int_ptr_type_node = build_pointer_type (integer_type_node);
2664 record = make_node (RECORD_TYPE);
2666 field_arg = build_decl (FIELD_DECL, get_identifier ("__va_arg"),
2668 field_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"),
2670 field_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),
2673 DECL_FIELD_CONTEXT (field_arg) = record;
2674 DECL_FIELD_CONTEXT (field_stk) = record;
2675 DECL_FIELD_CONTEXT (field_reg) = record;
2677 TYPE_FIELDS (record) = field_arg;
2678 TREE_CHAIN (field_arg) = field_stk;
2679 TREE_CHAIN (field_stk) = field_reg;
2681 layout_type (record);
2685 /* Implement `va_start' for varargs and stdarg. */
2688 m88k_va_start (stdarg_p, valist, nextarg)
2689 int stdarg_p ATTRIBUTE_UNUSED;
2691 rtx nextarg ATTRIBUTE_UNUSED;
2693 tree field_reg, field_stk, field_arg;
2694 tree reg, stk, arg, t;
2696 field_arg = TYPE_FIELDS (va_list_type_node);
2697 field_stk = TREE_CHAIN (field_arg);
2698 field_reg = TREE_CHAIN (field_stk);
2700 arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
2701 stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
2702 reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
2704 /* Fill in the ARG member. */
2706 tree fntype = TREE_TYPE (current_function_decl);
2707 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2708 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2709 != void_type_node)))
2710 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
2713 if (CONSTANT_P (current_function_arg_offset_rtx))
2715 int fixed = (INTVAL (current_function_arg_offset_rtx)
2716 + argadj) / UNITS_PER_WORD;
2718 argsize = build_int_2 (fixed, 0);
2722 argsize = make_tree (integer_type_node,
2723 current_function_arg_offset_rtx);
2724 argsize = fold (build (PLUS_EXPR, integer_type_node, argsize,
2725 build_int_2 (argadj, 0)));
2726 argsize = fold (build (RSHIFT_EXPR, integer_type_node, argsize,
2727 build_int_2 (2, 0)));
2730 t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, argsize);
2731 TREE_SIDE_EFFECTS (t) = 1;
2732 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2735 /* Store the arg pointer in the __va_stk member. */
2736 t = make_tree (TREE_TYPE (stk), virtual_incoming_args_rtx);
2737 t = build (MODIFY_EXPR, TREE_TYPE (stk), stk, t);
2738 TREE_SIDE_EFFECTS (t) = 1;
2739 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2741 /* Tuck the return value from __builtin_saveregs into __va_reg. */
2742 t = make_tree (TREE_TYPE (reg), expand_builtin_saveregs ());
2743 t = build (MODIFY_EXPR, TREE_TYPE (reg), reg, t);
2744 TREE_SIDE_EFFECTS (t) = 1;
2745 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2748 /* Implement `va_arg'. */
2751 m88k_va_arg (valist, type)
2754 tree field_reg, field_stk, field_arg;
2755 tree reg, stk, arg, arg_align, base, t;
2756 int size, wsize, align, reg_p;
2759 field_arg = TYPE_FIELDS (va_list_type_node);
2760 field_stk = TREE_CHAIN (field_arg);
2761 field_reg = TREE_CHAIN (field_stk);
2763 arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
2764 stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
2765 reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
2767 size = int_size_in_bytes (type);
2768 wsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
2769 align = 1 << ((TYPE_ALIGN (type) / BITS_PER_UNIT) >> 3);
2770 reg_p = (AGGREGATE_TYPE_P (type)
2771 ? size == UNITS_PER_WORD && TYPE_ALIGN (type) == BITS_PER_WORD
2772 : size <= 2*UNITS_PER_WORD);
2774 /* Align __va_arg to the (doubleword?) boundary above. */
2775 t = build (PLUS_EXPR, TREE_TYPE (arg), arg, build_int_2 (align - 1, 0));
2776 arg_align = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
2777 arg_align = save_expr (arg_align);
2779 /* Decide if we should read from stack or regs. */
2780 t = build (LT_EXPR, integer_type_node, arg_align, build_int_2 (8, 0));
2781 base = build (COND_EXPR, TREE_TYPE (reg), t, reg, stk);
2783 /* Find the final address. */
2784 t = build (PLUS_EXPR, TREE_TYPE (base), base, arg_align);
2785 addr_rtx = expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
2786 addr_rtx = copy_to_reg (addr_rtx);
2788 /* Increment __va_arg. */
2789 t = build (PLUS_EXPR, TREE_TYPE (arg), arg_align, build_int_2 (wsize, 0));
2790 t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, t);
2791 TREE_SIDE_EFFECTS (t) = 1;
2792 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2797 /* If cmpsi has not been generated, emit code to do the test. Return the
2798 expression describing the test of operator OP. */
2801 emit_test (op, mode)
2803 enum machine_mode mode;
2805 if (m88k_compare_reg == 0)
2806 emit_insn (gen_test (m88k_compare_op0, m88k_compare_op1));
2807 return (gen_rtx (op, mode, m88k_compare_reg, const0_rtx));
2810 /* Determine how to best perform cmpsi/bxx, where cmpsi has a constant
2811 operand. All tests with zero (albeit swapped) and all equality tests
2812 with a constant are done with bcnd. The remaining cases are swapped
2816 emit_bcnd (op, label)
2820 if (m88k_compare_op1 == const0_rtx)
2821 emit_jump_insn (gen_bcnd
2822 (gen_rtx (op, VOIDmode,m88k_compare_op0, const0_rtx),
2824 else if (m88k_compare_op0 == const0_rtx)
2825 emit_jump_insn (gen_bcnd
2826 (gen_rtx (swap_condition (op),
2827 VOIDmode, m88k_compare_op1, const0_rtx),
2829 else if (op != EQ && op != NE)
2830 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2833 rtx zero = gen_reg_rtx (SImode);
2837 if (GET_CODE (m88k_compare_op1) == CONST_INT)
2839 reg = force_reg (SImode, m88k_compare_op0);
2840 constant = m88k_compare_op1;
2844 reg = force_reg (SImode, m88k_compare_op1);
2845 constant = m88k_compare_op0;
2847 value = INTVAL (constant);
2849 /* Perform an arithmetic computation to make the compared-to value
2850 zero, but avoid loosing if the bcnd is later changed into sxx. */
2851 if (SMALL_INTVAL (value))
2852 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2855 if (SMALL_INTVAL (-value))
2856 emit_insn (gen_addsi3 (zero, reg,
2859 emit_insn (gen_xorsi3 (zero, reg, constant));
2861 emit_jump_insn (gen_bcnd (gen_rtx (op, VOIDmode,
2868 /* Print an operand. Recognize special options, documented below. */
2871 print_operand (file, x, code)
2876 enum rtx_code xc = (x ? GET_CODE (x) : UNKNOWN);
2877 register int value = (xc == CONST_INT ? INTVAL (x) : 0);
2878 static int sequencep;
2879 static int reversep;
2883 if (code < 'B' || code > 'E')
2884 output_operand_lossage ("%R not followed by %B/C/D/E");
2886 xc = reverse_condition (xc);
2892 case '*': /* addressing base register for PIC */
2893 fputs (reg_names[PIC_OFFSET_TABLE_REGNUM], file); return;
2895 case '#': /* SVR4 pound-sign syntax character (empty if SVR3) */
2896 fputs (m88k_pound_sign, file); return;
2898 case 'V': /* Output a serializing instruction as needed if the operand
2899 (assumed to be a MEM) is a volatile load. */
2900 case 'v': /* ditto for a volatile store. */
2901 if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE)
2903 /* The m88110 implements two FIFO queues, one for loads and
2904 one for stores. These queues mean that loads complete in
2905 their issue order as do stores. An interaction between the
2906 history buffer and the store reservation station ensures
2907 that a store will not bypass load. Finally, a load will not
2908 bypass store, but only when they reference the same address.
2910 To avoid this reordering (a load bypassing a store) for
2911 volatile references, a serializing instruction is output.
2912 We choose the fldcr instruction as it does not serialize on
2913 the m88100 so that -m88000 code will not be degraded.
2915 The mechanism below is completed by having CC_STATUS_INIT set
2916 the code to the unknown value. */
2920 A problem with 88110 4.1 & 4.2 makes the use of fldcr for
2921 this purpose undesirable. Instead we will use tb1, this will
2922 cause serialization on the 88100 but such is life.
2925 static rtx last_addr = 0;
2926 if (code == 'V' /* Only need to serialize before a load. */
2927 && m88k_volatile_code != 'V' /* Loads complete in FIFO order. */
2928 && !(m88k_volatile_code == 'v'
2929 && GET_CODE (XEXP (x, 0)) == LO_SUM
2930 && rtx_equal_p (XEXP (XEXP (x, 0), 1), last_addr)))
2934 "fldcr\t %s,%scr63\n\t",
2936 "fldcr\t %s,%sfcr63\n\t",
2938 reg_names[0], m88k_pound_sign);
2940 "tb1\t 1,%s,0xff\n\t", reg_names[0]);
2942 m88k_volatile_code = code;
2943 last_addr = (GET_CODE (XEXP (x, 0)) == LO_SUM
2944 ? XEXP (XEXP (x, 0), 1) : 0);
2948 case 'X': /* print the upper 16 bits... */
2950 case 'x': /* print the lower 16 bits of the integer constant in hex */
2951 if (xc != CONST_INT)
2952 output_operand_lossage ("invalid %x/X value");
2953 fprintf (file, "0x%x", value & 0xffff); return;
2955 case 'H': /* print the low 16 bits of the negated integer constant */
2956 if (xc != CONST_INT)
2957 output_operand_lossage ("invalid %H value");
2959 case 'h': /* print the register or low 16 bits of the integer constant */
2962 if (xc != CONST_INT)
2963 output_operand_lossage ("invalid %h value");
2964 fprintf (file, "%d", value & 0xffff);
2967 case 'Q': /* print the low 8 bits of the negated integer constant */
2968 if (xc != CONST_INT)
2969 output_operand_lossage ("invalid %Q value");
2971 case 'q': /* print the register or low 8 bits of the integer constant */
2974 if (xc != CONST_INT)
2975 output_operand_lossage ("invalid %q value");
2976 fprintf (file, "%d", value & 0xff);
2979 case 'w': /* print the integer constant (X == 32 ? 0 : 32 - X) */
2980 if (xc != CONST_INT)
2981 output_operand_lossage ("invalid %o value");
2982 fprintf (file, "%d", value == 32 ? 0 : 32 - value);
2985 case 'p': /* print the logarithm of the integer constant */
2987 || (value = exact_log2 (value)) < 0)
2988 output_operand_lossage ("invalid %p value");
2989 fprintf (file, "%d", value);
2992 case 'S': /* compliment the value and then... */
2994 case 's': /* print the width and offset values forming the integer
2995 constant with a SET instruction. See integer_ok_for_set. */
2997 register unsigned mask, uval = value;
2998 register int top, bottom;
3000 if (xc != CONST_INT)
3001 output_operand_lossage ("invalid %s/S value");
3002 /* All the "one" bits must be contiguous. If so, MASK will be
3003 a power of two or zero. */
3004 mask = (uval | (uval - 1)) + 1;
3005 if (!(uval && POWER_OF_2_or_0 (mask)))
3006 output_operand_lossage ("invalid %s/S value");
3007 top = mask ? exact_log2 (mask) : 32;
3008 bottom = exact_log2 (uval & ~(uval - 1));
3009 fprintf (file,"%d<%d>", top - bottom, bottom);
3013 case 'P': /* print nothing if pc_rtx; output label_ref */
3014 if (xc == LABEL_REF)
3015 output_addr_const (file, x);
3017 output_operand_lossage ("invalid %P operand");
3020 case 'L': /* print 0 or 1 if operand is label_ref and then... */
3021 fputc (xc == LABEL_REF ? '1' : '0', file);
3022 case '.': /* print .n if delay slot is used */
3023 fputs ((final_sequence
3024 && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
3025 ? ".n\t" : "\t", file);
3028 case '!': /* Reverse the following condition. */
3032 case 'R': /* reverse the condition of the next print_operand
3033 if operand is a label_ref. */
3035 reversep = (xc == LABEL_REF);
3038 case 'B': /* bcnd branch values */
3039 fputs (m88k_pound_sign, file);
3042 case EQ: fputs ("eq0", file); return;
3043 case NE: fputs ("ne0", file); return;
3044 case GT: fputs ("gt0", file); return;
3045 case LE: fputs ("le0", file); return;
3046 case LT: fputs ("lt0", file); return;
3047 case GE: fputs ("ge0", file); return;
3048 default: output_operand_lossage ("invalid %B value");
3051 case 'C': /* bb0/bb1 branch values for comparisons */
3052 fputs (m88k_pound_sign, file);
3055 case EQ: fputs ("eq", file); return;
3056 case NE: fputs ("ne", file); return;
3057 case GT: fputs ("gt", file); return;
3058 case LE: fputs ("le", file); return;
3059 case LT: fputs ("lt", file); return;
3060 case GE: fputs ("ge", file); return;
3061 case GTU: fputs ("hi", file); return;
3062 case LEU: fputs ("ls", file); return;
3063 case LTU: fputs ("lo", file); return;
3064 case GEU: fputs ("hs", file); return;
3065 default: output_operand_lossage ("invalid %C value");
3068 case 'D': /* bcnd branch values for float comparisons */
3071 case EQ: fputs ("0xa", file); return;
3072 case NE: fputs ("0x5", file); return;
3073 case GT: fputs (m88k_pound_sign, file);
3074 fputs ("gt0", file); return;
3075 case LE: fputs ("0xe", file); return;
3076 case LT: fputs ("0x4", file); return;
3077 case GE: fputs ("0xb", file); return;
3078 default: output_operand_lossage ("invalid %D value");
3081 case 'E': /* bcnd branch values for special integers */
3084 case EQ: fputs ("0x8", file); return;
3085 case NE: fputs ("0x7", file); return;
3086 default: output_operand_lossage ("invalid %E value");
3089 case 'd': /* second register of a two register pair */
3091 output_operand_lossage ("`%d' operand isn't a register");
3092 fputs (reg_names[REGNO (x) + 1], file);
3095 case 'r': /* an immediate 0 should be represented as `r0' */
3096 if (x == const0_rtx)
3098 fputs (reg_names[0], file);
3102 output_operand_lossage ("invalid %r value");
3108 if (REGNO (x) == ARG_POINTER_REGNUM)
3109 output_operand_lossage ("operand is r0");
3111 fputs (reg_names[REGNO (x)], file);
3113 else if (xc == PLUS)
3116 output_address (XEXP (x, 0));
3117 else if (flag_pic && xc == UNSPEC)
3119 output_addr_const (file, XVECEXP (x, 0, 0));
3120 fputs ("#got_rel", file);
3122 else if (xc == CONST_DOUBLE)
3123 output_operand_lossage ("operand is const_double");
3125 output_addr_const (file, x);
3128 case 'g': /* append #got_rel as needed */
3129 if (flag_pic && (xc == SYMBOL_REF || xc == LABEL_REF))
3131 output_addr_const (file, x);
3132 fputs ("#got_rel", file);
3137 case 'a': /* (standard), assume operand is an address */
3138 case 'c': /* (standard), assume operand is an immediate value */
3139 case 'l': /* (standard), assume operand is a label_ref */
3140 case 'n': /* (standard), like %c, except negate first */
3142 output_operand_lossage ("invalid code");
3147 print_operand_address (file, addr)
3151 register rtx reg0, reg1, temp;
3153 switch (GET_CODE (addr))
3156 if (REGNO (addr) == ARG_POINTER_REGNUM)
3159 fprintf (file, "%s,%s", reg_names[0], reg_names [REGNO (addr)]);
3163 fprintf (file, "%s,%slo16(",
3164 reg_names[REGNO (XEXP (addr, 0))], m88k_pound_sign);
3165 output_addr_const (file, XEXP (addr, 1));
3170 reg0 = XEXP (addr, 0);
3171 reg1 = XEXP (addr, 1);
3172 if (GET_CODE (reg0) == MULT || GET_CODE (reg0) == CONST_INT)
3179 if ((REG_P (reg0) && REGNO (reg0) == ARG_POINTER_REGNUM)
3180 || (REG_P (reg1) && REGNO (reg1) == ARG_POINTER_REGNUM))
3183 else if (REG_P (reg0))
3186 fprintf (file, "%s,%s",
3187 reg_names [REGNO (reg0)], reg_names [REGNO (reg1)]);
3189 else if (GET_CODE (reg1) == CONST_INT)
3190 fprintf (file, "%s,%d",
3191 reg_names [REGNO (reg0)], INTVAL (reg1));
3193 else if (GET_CODE (reg1) == MULT)
3195 rtx mreg = XEXP (reg1, 0);
3196 if (REGNO (mreg) == ARG_POINTER_REGNUM)
3199 fprintf (file, "%s[%s]", reg_names[REGNO (reg0)],
3200 reg_names[REGNO (mreg)]);
3203 else if (GET_CODE (reg1) == ZERO_EXTRACT)
3205 fprintf (file, "%s,%slo16(",
3206 reg_names[REGNO (reg0)], m88k_pound_sign);
3207 output_addr_const (file, XEXP (reg1, 0));
3213 fprintf (file, "%s,", reg_names[REGNO (reg0)]);
3214 output_addr_const (file, reg1);
3215 fputs ("#got_rel", file);
3225 if (REGNO (XEXP (addr, 0)) == ARG_POINTER_REGNUM)
3228 fprintf (file, "%s[%s]",
3229 reg_names[0], reg_names[REGNO (XEXP (addr, 0))]);
3233 fprintf (file, "%s,%d", reg_names[0], INTVAL (addr));
3237 fprintf (file, "%s,", reg_names[0]);
3238 if (SHORT_ADDRESS_P (addr, temp))
3240 fprintf (file, "%siw16(", m88k_pound_sign);
3241 output_addr_const (file, addr);
3245 output_addr_const (file, addr);
3249 /* Return true if X is an address which needs a temporary register when
3250 reloaded while generating PIC code. */
3253 pic_address_needs_scratch (x)
3256 /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */
3257 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
3258 && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
3259 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
3260 && ! ADD_INT (XEXP (XEXP (x, 0), 1)))
3266 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
3267 reference and a constant. */
3270 symbolic_operand (op, mode)
3272 enum machine_mode mode;
3274 switch (GET_CODE (op))
3282 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
3283 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
3284 && GET_CODE (XEXP (op, 1)) == CONST_INT);
3286 /* ??? This clause seems to be irrelevant. */
3288 return GET_MODE (op) == mode;
3295 #ifdef INIT_SECTION_ASM_OP
3297 m88k_svr3_asm_out_constructor (symbol, priority)
3299 int priority ATTRIBUTE_UNUSED;
3301 const char *name = XSTR (symbol, 0);
3304 fprintf (asm_out_file, "\tor.u\t r13,r0,hi16(");
3305 assemble_name (asm_out_file, name);
3306 fprintf (asm_out_file, ")\n\tor\t r13,r13,lo16(");
3307 assemble_name (asm_out_file, name);
3308 fprintf (asm_out_file, ")\n\tsubu\t r31,r31,%d\n\tst\t r13,r31,%d\n",
3309 STACK_BOUNDARY / BITS_PER_UNIT, REG_PARM_STACK_SPACE (0));
3313 m88k_svr3_asm_out_destructor (symbol, priority)
3315 int priority ATTRIBUTE_UNUSED;
3320 assemble_integer (symbol, UNITS_PER_WORD, BITS_PER_WORD, 1);
3321 for (i = 1; i < 4; i++)
3322 assemble_integer (constm1_rtx, UNITS_PER_WORD, BITS_PER_WORD, 1);
3326 /* Adjust the cost of INSN based on the relationship between INSN that
3327 is dependent on DEP_INSN through the dependence LINK. The default
3328 is to make no adjustment to COST.
3330 On the m88k, ignore the cost of anti- and output-dependencies. On
3331 the m88100, a store can issue two cycles before the value (not the
3332 address) has finished computing. */
3335 m88k_adjust_cost (insn, link, dep, cost)
3341 if (REG_NOTE_KIND (link) != 0)
3342 return 0; /* Anti or output dependence. */
3345 && recog_memoized (insn) >= 0
3346 && get_attr_type (insn) == TYPE_STORE
3347 && SET_SRC (PATTERN (insn)) == SET_DEST (PATTERN (dep)))
3348 return cost - 4; /* 88110 store reservation station. */