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 FILE *asm_out_file;
48 const char *m88k_pound_sign = ""; /* Either # for SVR4 or empty for SVR3 */
49 const char *m88k_short_data;
50 const char *m88k_version;
51 char m88k_volatile_code;
53 unsigned m88k_gp_threshold = 0;
54 int m88k_prologue_done = 0; /* Ln directives can now be emitted */
55 int m88k_function_number = 0; /* Counter unique to each function */
56 int m88k_fp_offset = 0; /* offset of frame pointer if used */
57 int m88k_stack_size = 0; /* size of allocated stack (including frame) */
60 rtx m88k_compare_reg; /* cmp output pseudo register */
61 rtx m88k_compare_op0; /* cmpsi operand 0 */
62 rtx m88k_compare_op1; /* cmpsi operand 1 */
64 enum processor_type m88k_cpu; /* target cpu */
66 static void m88k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
67 static void m88k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
68 static void m88k_output_function_end_prologue PARAMS ((FILE *));
69 static void m88k_output_function_begin_epilogue PARAMS ((FILE *));
70 #if defined (CTOR_LIST_BEGIN) && !defined (OBJECT_FORMAT_ELF)
71 static void m88k_svr3_asm_out_constructor PARAMS ((rtx, int));
72 static void m88k_svr3_asm_out_destructor PARAMS ((rtx, int));
75 static int m88k_adjust_cost PARAMS ((rtx, rtx, rtx, int));
77 /* Initialize the GCC target structure. */
78 #undef TARGET_ASM_BYTE_OP
79 #define TARGET_ASM_BYTE_OP "\tbyte\t"
80 #undef TARGET_ASM_ALIGNED_HI_OP
81 #define TARGET_ASM_ALIGNED_HI_OP "\thalf\t"
82 #undef TARGET_ASM_ALIGNED_SI_OP
83 #define TARGET_ASM_ALIGNED_SI_OP "\tword\t"
84 #undef TARGET_ASM_UNALIGNED_HI_OP
85 #define TARGET_ASM_UNALIGNED_HI_OP "\tuahalf\t"
86 #undef TARGET_ASM_UNALIGNED_SI_OP
87 #define TARGET_ASM_UNALIGNED_SI_OP "\tuaword\t"
89 #undef TARGET_ASM_FUNCTION_PROLOGUE
90 #define TARGET_ASM_FUNCTION_PROLOGUE m88k_output_function_prologue
91 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
92 #define TARGET_ASM_FUNCTION_END_PROLOGUE m88k_output_function_end_prologue
93 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
94 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE m88k_output_function_begin_epilogue
95 #undef TARGET_ASM_FUNCTION_EPILOGUE
96 #define TARGET_ASM_FUNCTION_EPILOGUE m88k_output_function_epilogue
98 #undef TARGET_SCHED_ADJUST_COST
99 #define TARGET_SCHED_ADJUST_COST m88k_adjust_cost
101 struct gcc_target targetm = TARGET_INITIALIZER;
103 /* Determine what instructions are needed to manufacture the integer VALUE
104 in the given MODE. */
106 enum m88k_instruction
107 classify_integer (mode, value)
108 enum machine_mode mode;
113 else if (SMALL_INTVAL (value))
115 else if (SMALL_INTVAL (-value))
117 else if (mode == HImode)
119 else if (mode == QImode)
121 else if ((value & 0xffff) == 0)
122 return m88k_oru_hi16;
123 else if (integer_ok_for_set (value))
129 /* Return the bit number in a compare word corresponding to CONDITION. */
132 condition_value (condition)
135 switch (GET_CODE (condition))
152 integer_ok_for_set (value)
153 register unsigned value;
155 /* All the "one" bits must be contiguous. If so, MASK + 1 will be
156 a power of two or zero. */
157 register unsigned mask = (value | (value - 1));
158 return (value && POWER_OF_2_or_0 (mask + 1));
162 output_load_const_int (mode, operands)
163 enum machine_mode mode;
166 static const char *const patterns[] =
174 "or.u %0,%#r0,%X1\n\tor %0,%0,%x1",
177 if (! REG_P (operands[0])
178 || GET_CODE (operands[1]) != CONST_INT)
180 return patterns[classify_integer (mode, INTVAL (operands[1]))];
183 /* These next two routines assume that floating point numbers are represented
184 in a manner which is consistent between host and target machines. */
187 output_load_const_float (operands)
190 /* These can return 0 under some circumstances when cross-compiling. */
191 operands[0] = operand_subword (operands[0], 0, 0, SFmode);
192 operands[1] = operand_subword (operands[1], 0, 0, SFmode);
194 return output_load_const_int (SImode, operands);
198 output_load_const_double (operands)
203 /* These can return zero on some cross-compilers, but there's nothing
204 we can do about it. */
205 latehalf[0] = operand_subword (operands[0], 1, 0, DFmode);
206 latehalf[1] = operand_subword (operands[1], 1, 0, DFmode);
208 operands[0] = operand_subword (operands[0], 0, 0, DFmode);
209 operands[1] = operand_subword (operands[1], 0, 0, DFmode);
211 output_asm_insn (output_load_const_int (SImode, operands), operands);
213 operands[0] = latehalf[0];
214 operands[1] = latehalf[1];
216 return output_load_const_int (SImode, operands);
220 output_load_const_dimode (operands)
225 latehalf[0] = operand_subword (operands[0], 1, 0, DImode);
226 latehalf[1] = operand_subword (operands[1], 1, 0, DImode);
228 operands[0] = operand_subword (operands[0], 0, 0, DImode);
229 operands[1] = operand_subword (operands[1], 0, 0, DImode);
231 output_asm_insn (output_load_const_int (SImode, operands), operands);
233 operands[0] = latehalf[0];
234 operands[1] = latehalf[1];
236 return output_load_const_int (SImode, operands);
239 /* Emit insns to move operands[1] into operands[0].
241 Return 1 if we have written out everything that needs to be done to
242 do the move. Otherwise, return 0 and the caller will emit the move
245 SCRATCH if non zero can be used as a scratch register for the move
246 operation. It is provided by a SECONDARY_RELOAD_* macro if needed. */
249 emit_move_sequence (operands, mode, scratch)
251 enum machine_mode mode;
254 register rtx operand0 = operands[0];
255 register rtx operand1 = operands[1];
257 if (CONSTANT_P (operand1) && flag_pic
258 && pic_address_needs_scratch (operand1))
259 operands[1] = operand1 = legitimize_address (1, operand1, 0, 0);
261 /* Handle most common case first: storing into a register. */
262 if (register_operand (operand0, mode))
264 if (register_operand (operand1, mode)
265 || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
266 || GET_CODE (operand1) == HIGH
267 /* Only `general_operands' can come here, so MEM is ok. */
268 || GET_CODE (operand1) == MEM)
270 /* Run this case quickly. */
271 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
275 else if (GET_CODE (operand0) == MEM)
277 if (register_operand (operand1, mode)
278 || (operand1 == const0_rtx && GET_MODE_SIZE (mode) <= UNITS_PER_WORD))
280 /* Run this case quickly. */
281 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
284 if (! reload_in_progress && ! reload_completed)
286 operands[0] = validize_mem (operand0);
287 operands[1] = operand1 = force_reg (mode, operand1);
291 /* Simplify the source if we need to. */
292 if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
294 if (GET_CODE (operand1) != CONST_INT
295 && GET_CODE (operand1) != CONST_DOUBLE)
297 rtx temp = ((reload_in_progress || reload_completed)
299 operands[1] = legitimize_address (flag_pic
300 && symbolic_address_p (operand1),
301 operand1, temp, scratch);
303 operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
307 /* Now have insn-emit do whatever it normally does. */
311 /* Return a legitimate reference for ORIG (either an address or a MEM)
312 using the register REG. If PIC and the address is already
313 position-independent, use ORIG. Newly generated position-independent
314 addresses go into a reg. This is REG if non zero, otherwise we
315 allocate register(s) as necessary. If this is called during reload,
316 and we need a second temp register, then we use SCRATCH, which is
317 provided via the SECONDARY_INPUT_RELOAD_CLASS mechanism. */
320 legitimize_address (pic, orig, reg, scratch)
326 rtx addr = (GET_CODE (orig) == MEM ? XEXP (orig, 0) : orig);
332 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
336 if (reload_in_progress || reload_completed)
339 reg = gen_reg_rtx (Pmode);
344 /* If not during reload, allocate another temp reg here for
345 loading in the address, so that these instructions can be
346 optimized properly. */
347 temp = ((reload_in_progress || reload_completed)
348 ? reg : gen_reg_rtx (Pmode));
350 emit_insn (gen_rtx_SET
352 gen_rtx_HIGH (SImode,
353 gen_rtx_UNSPEC (SImode,
357 emit_insn (gen_rtx_SET
359 gen_rtx_LO_SUM (SImode, temp,
360 gen_rtx_UNSPEC (SImode,
366 new = gen_rtx_MEM (Pmode,
367 gen_rtx_PLUS (SImode,
368 pic_offset_table_rtx, addr));
370 current_function_uses_pic_offset_table = 1;
371 RTX_UNCHANGING_P (new) = 1;
372 insn = emit_move_insn (reg, new);
373 /* Put a REG_EQUAL note on this insn, so that it can be optimized
375 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
379 else if (GET_CODE (addr) == CONST)
383 if (GET_CODE (XEXP (addr, 0)) == PLUS
384 && XEXP (XEXP (addr, 0), 0) == pic_offset_table_rtx)
389 if (reload_in_progress || reload_completed)
392 reg = gen_reg_rtx (Pmode);
395 if (GET_CODE (XEXP (addr, 0)) != PLUS) abort ();
397 base = legitimize_address (1, XEXP (XEXP (addr, 0), 0), reg, 0);
398 addr = legitimize_address (1, XEXP (XEXP (addr, 0), 1),
399 base == reg ? 0 : reg, 0);
401 if (GET_CODE (addr) == CONST_INT)
404 return plus_constant (base, INTVAL (addr));
405 else if (! reload_in_progress && ! reload_completed)
406 addr = force_reg (Pmode, addr);
407 /* We can't create any new registers during reload, so use the
408 SCRATCH reg provided by the reload_insi pattern. */
411 emit_move_insn (scratch, addr);
415 /* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS
416 macro needs to be adjusted so that a scratch reg is provided
420 new = gen_rtx_PLUS (SImode, base, addr);
421 /* Should we set special REG_NOTEs here? */
424 else if (! SHORT_ADDRESS_P (addr, temp))
428 if (reload_in_progress || reload_completed)
431 reg = gen_reg_rtx (Pmode);
434 emit_insn (gen_rtx_SET (VOIDmode,
435 reg, gen_rtx_HIGH (SImode, addr)));
436 new = gen_rtx_LO_SUM (SImode, reg, addr);
440 && GET_CODE (orig) == MEM)
442 new = gen_rtx_MEM (GET_MODE (orig), new);
443 MEM_COPY_ATTRIBUTES (new, orig);
448 /* Support functions for code to emit a block move. There are four methods
449 used to perform the block move:
451 + call the looping library function, e.g. __movstrSI64n8
452 + call a non-looping library function, e.g. __movstrHI15x11
453 + produce an inline sequence of ld/st instructions
455 The parameters below describe the library functions produced by
458 #define MOVSTR_LOOP 64 /* __movstrSI64n68 .. __movstrSI64n8 */
459 #define MOVSTR_QI 16 /* __movstrQI16x16 .. __movstrQI16x2 */
460 #define MOVSTR_HI 48 /* __movstrHI48x48 .. __movstrHI48x4 */
461 #define MOVSTR_SI 96 /* __movstrSI96x96 .. __movstrSI96x8 */
462 #define MOVSTR_DI 96 /* __movstrDI96x96 .. __movstrDI96x16 */
463 #define MOVSTR_ODD_HI 16 /* __movstrHI15x15 .. __movstrHI15x5 */
464 #define MOVSTR_ODD_SI 48 /* __movstrSI47x47 .. __movstrSI47x11,
465 __movstrSI46x46 .. __movstrSI46x10,
466 __movstrSI45x45 .. __movstrSI45x9 */
467 #define MOVSTR_ODD_DI 48 /* __movstrDI47x47 .. __movstrDI47x23,
468 __movstrDI46x46 .. __movstrDI46x22,
469 __movstrDI45x45 .. __movstrDI45x21,
470 __movstrDI44x44 .. __movstrDI44x20,
471 __movstrDI43x43 .. __movstrDI43x19,
472 __movstrDI42x42 .. __movstrDI42x18,
473 __movstrDI41x41 .. __movstrDI41x17 */
475 /* Limits for using the non-looping movstr functions. For the m88100
476 processor, we assume the source and destination are word aligned.
477 The QImode and HImode limits are the break even points where memcpy
478 does just as well and beyond which memcpy does better. For the
479 m88110, we tend to assume double word alignment, but also analyze
480 the word aligned cases. The analysis is complicated because memcpy
481 may use the cache control instructions for better performance. */
483 #define MOVSTR_QI_LIMIT_88100 13
484 #define MOVSTR_HI_LIMIT_88100 38
485 #define MOVSTR_SI_LIMIT_88100 MOVSTR_SI
486 #define MOVSTR_DI_LIMIT_88100 MOVSTR_SI
488 #define MOVSTR_QI_LIMIT_88000 16
489 #define MOVSTR_HI_LIMIT_88000 38
490 #define MOVSTR_SI_LIMIT_88000 72
491 #define MOVSTR_DI_LIMIT_88000 72
493 #define MOVSTR_QI_LIMIT_88110 16
494 #define MOVSTR_HI_LIMIT_88110 38
495 #define MOVSTR_SI_LIMIT_88110 72
496 #define MOVSTR_DI_LIMIT_88110 72
498 static const enum machine_mode mode_from_align[] =
499 {VOIDmode, QImode, HImode, VOIDmode, SImode,
500 VOIDmode, VOIDmode, VOIDmode, DImode};
501 static const int max_from_align[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI,
503 static const int all_from_align[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0,
504 MOVSTR_ODD_SI, 0, 0, 0, MOVSTR_ODD_DI};
506 static const int best_from_align[3][9] = {
507 {0, MOVSTR_QI_LIMIT_88100, MOVSTR_HI_LIMIT_88100, 0, MOVSTR_SI_LIMIT_88100,
508 0, 0, 0, MOVSTR_DI_LIMIT_88100},
509 {0, MOVSTR_QI_LIMIT_88110, MOVSTR_HI_LIMIT_88110, 0, MOVSTR_SI_LIMIT_88110,
510 0, 0, 0, MOVSTR_DI_LIMIT_88110},
511 {0, MOVSTR_QI_LIMIT_88000, MOVSTR_HI_LIMIT_88000, 0, MOVSTR_SI_LIMIT_88000,
512 0, 0, 0, MOVSTR_DI_LIMIT_88000}
515 static void block_move_loop PARAMS ((rtx, rtx, rtx, rtx, int, int));
516 static void block_move_no_loop PARAMS ((rtx, rtx, rtx, rtx, int, int));
517 static void block_move_sequence PARAMS ((rtx, rtx, rtx, rtx, int, int, int));
518 static void output_short_branch_defs PARAMS ((FILE *));
519 static int output_option PARAMS ((FILE *, const char *, const char *,
520 const char *, const char *, int, int));
522 /* Emit code to perform a block move. Choose the best method.
524 OPERANDS[0] is the destination.
525 OPERANDS[1] is the source.
526 OPERANDS[2] is the size.
527 OPERANDS[3] is the alignment safe to use. */
530 expand_block_move (dest_mem, src_mem, operands)
535 int align = INTVAL (operands[3]);
536 int constp = (GET_CODE (operands[2]) == CONST_INT);
537 int bytes = (constp ? INTVAL (operands[2]) : 0);
538 int target = (int) m88k_cpu;
540 if (! (PROCESSOR_M88100 == 0
541 && PROCESSOR_M88110 == 1
542 && PROCESSOR_M88000 == 2))
545 if (constp && bytes <= 0)
548 /* Determine machine mode to do move with. */
549 if (align > 4 && !TARGET_88110)
551 else if (align <= 0 || align == 3)
552 abort (); /* block move invalid alignment. */
554 if (constp && bytes <= 3 * align)
555 block_move_sequence (operands[0], dest_mem, operands[1], src_mem,
558 else if (constp && bytes <= best_from_align[target][align])
559 block_move_no_loop (operands[0], dest_mem, operands[1], src_mem,
562 else if (constp && align == 4 && TARGET_88100)
563 block_move_loop (operands[0], dest_mem, operands[1], src_mem,
568 #ifdef TARGET_MEM_FUNCTIONS
569 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "memcpy"), 0,
573 convert_to_mode (TYPE_MODE (sizetype), operands[2],
574 TREE_UNSIGNED (sizetype)),
575 TYPE_MODE (sizetype));
577 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "bcopy"), 0,
581 convert_to_mode (TYPE_MODE (integer_type_node),
583 TREE_UNSIGNED (integer_type_node)),
584 TYPE_MODE (integer_type_node));
589 /* Emit code to perform a block move by calling a looping movstr library
590 function. SIZE and ALIGN are known constants. DEST and SRC are
594 block_move_loop (dest, dest_mem, src, src_mem, size, align)
600 enum machine_mode mode;
609 /* Determine machine mode to do move with. */
613 /* Determine the structure of the loop. */
614 count = size / MOVSTR_LOOP;
615 units = (size - count * MOVSTR_LOOP) / align;
620 units += MOVSTR_LOOP / align;
625 block_move_no_loop (dest, dest_mem, src, src_mem, size, align);
629 remainder = size - count * MOVSTR_LOOP - units * align;
631 mode = mode_from_align[align];
632 sprintf (entry, "__movstr%s%dn%d",
633 GET_MODE_NAME (mode), MOVSTR_LOOP, units * align);
634 entry_name = get_identifier (entry);
636 offset_rtx = GEN_INT (MOVSTR_LOOP + (1 - units) * align);
638 value_rtx = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode,
640 gen_rtx_REG (Pmode, 3),
642 MEM_COPY_ATTRIBUTES (value_rtx, src_mem);
644 emit_insn (gen_call_movstrsi_loop
645 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)),
646 dest, src, offset_rtx, value_rtx,
647 gen_rtx_REG (mode, ((units & 1) ? 4 : 5)),
651 block_move_sequence (gen_rtx_REG (Pmode, 2), dest_mem,
652 gen_rtx_REG (Pmode, 3), src_mem,
653 remainder, align, MOVSTR_LOOP + align);
656 /* Emit code to perform a block move by calling a non-looping library
657 function. SIZE and ALIGN are known constants. DEST and SRC are
658 registers. OFFSET is the known starting point for the output pattern. */
661 block_move_no_loop (dest, dest_mem, src, src_mem, size, align)
667 enum machine_mode mode = mode_from_align[align];
668 int units = size / align;
669 int remainder = size - units * align;
677 if (remainder && size <= all_from_align[align])
679 most = all_from_align[align] - (align - remainder);
684 most = max_from_align[align];
687 sprintf (entry, "__movstr%s%dx%d",
688 GET_MODE_NAME (mode), most, size - remainder);
689 entry_name = get_identifier (entry);
691 offset_rtx = GEN_INT (most - (size - remainder));
693 value_rtx = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode,
695 gen_rtx_REG (Pmode, 3),
698 MEM_COPY_ATTRIBUTES (value_rtx, src_mem);
700 value_reg = ((((most - (size - remainder)) / align) & 1) == 0
701 ? (align == 8 ? 6 : 5) : 4);
703 emit_insn (gen_call_block_move
704 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)),
705 dest, src, offset_rtx, value_rtx,
706 gen_rtx_REG (mode, value_reg)));
709 block_move_sequence (gen_rtx_REG (Pmode, 2), dest_mem,
710 gen_rtx_REG (Pmode, 3), src_mem,
711 remainder, align, most);
714 /* Emit code to perform a block move with an offset sequence of ld/st
715 instructions (..., ld 0, st 1, ld 1, st 0, ...). SIZE and ALIGN are
716 known constants. DEST and SRC are registers. OFFSET is the known
717 starting point for the output pattern. */
720 block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset)
728 enum machine_mode mode[2];
733 int offset_ld = offset;
734 int offset_st = offset;
736 active[0] = active[1] = FALSE;
738 /* Establish parameters for the first load and for the second load if
739 it is known to be the same mode as the first. */
740 amount[0] = amount[1] = align;
741 mode[0] = mode_from_align[align];
742 temp[0] = gen_reg_rtx (mode[0]);
743 if (size >= 2 * align)
746 temp[1] = gen_reg_rtx (mode[1]);
757 /* Change modes as the sequence tails off. */
758 if (size < amount[next])
760 amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1));
761 mode[next] = mode_from_align[amount[next]];
762 temp[next] = gen_reg_rtx (mode[next]);
764 size -= amount[next];
765 srcp = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode[next] : BLKmode,
766 plus_constant (src, offset_ld));
768 MEM_COPY_ATTRIBUTES (srcp, src_mem);
769 emit_insn (gen_rtx_SET (VOIDmode, temp[next], srcp));
770 offset_ld += amount[next];
776 active[phase] = FALSE;
778 = gen_rtx_MEM (MEM_IN_STRUCT_P (dest_mem) ? mode[phase] : BLKmode,
779 plus_constant (dest, offset_st));
781 MEM_COPY_ATTRIBUTES (dstp, dest_mem);
782 emit_insn (gen_rtx_SET (VOIDmode, dstp, temp[phase]));
783 offset_st += amount[phase];
786 while (active[next]);
789 /* Emit the code to do an AND operation. */
792 output_and (operands)
797 if (REG_P (operands[2]))
798 return "and %0,%1,%2";
800 value = INTVAL (operands[2]);
801 if (SMALL_INTVAL (value))
802 return "mask %0,%1,%2";
803 else if ((value & 0xffff0000) == 0xffff0000)
804 return "and %0,%1,%x2";
805 else if ((value & 0xffff) == 0xffff)
806 return "and.u %0,%1,%X2";
807 else if ((value & 0xffff) == 0)
808 return "mask.u %0,%1,%X2";
809 else if (integer_ok_for_set (~value))
810 return "clr %0,%1,%S2";
812 return "and.u %0,%1,%X2\n\tand %0,%0,%x2";
815 /* Emit the code to do an inclusive OR operation. */
818 output_ior (operands)
823 if (REG_P (operands[2]))
824 return "or %0,%1,%2";
826 value = INTVAL (operands[2]);
827 if (SMALL_INTVAL (value))
828 return "or %0,%1,%2";
829 else if ((value & 0xffff) == 0)
830 return "or.u %0,%1,%X2";
831 else if (integer_ok_for_set (value))
832 return "set %0,%1,%s2";
834 return "or.u %0,%1,%X2\n\tor %0,%0,%x2";
837 /* Emit the instructions for doing an XOR. */
840 output_xor (operands)
845 if (REG_P (operands[2]))
846 return "xor %0,%1,%2";
848 value = INTVAL (operands[2]);
849 if (SMALL_INTVAL (value))
850 return "xor %0,%1,%2";
851 else if ((value & 0xffff) == 0)
852 return "xor.u %0,%1,%X2";
854 return "xor.u %0,%1,%X2\n\txor %0,%0,%x2";
857 /* Output a call. Normally this is just bsr or jsr, but this also deals with
858 accomplishing a branch after the call by incrementing r1. This requires
859 that various assembler bugs be accommodated. The 4.30 DG/UX assembler
860 requires that forward references not occur when computing the difference of
861 two labels. The [version?] Motorola assembler computes a word difference.
862 No doubt there's more to come!
864 It would seem the same idea could be used to tail call, but in this case,
865 the epilogue will be non-null. */
867 static rtx sb_name = 0;
868 static rtx sb_high = 0;
869 static rtx sb_low = 0;
872 output_call (operands, addr)
882 /* This can be generalized, but there is currently no need. */
883 if (XVECLEN (final_sequence, 0) != 2)
886 /* The address of interior insns is not computed, so use the sequence. */
887 seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
888 jump = XVECEXP (final_sequence, 0, 1);
889 if (GET_CODE (jump) == JUMP_INSN)
893 rtx dest = XEXP (SET_SRC (PATTERN (jump)), 0);
894 int delta = 4 * (INSN_ADDRESSES (INSN_UID (dest))
895 - INSN_ADDRESSES (INSN_UID (seq_insn))
897 #if (MONITOR_GCC & 0x2) /* How often do long branches happen? */
898 if ((unsigned) (delta + 0x8000) >= 0x10000)
899 warning ("internal gcc monitor: short-branch(%x)", delta);
902 /* Delete the jump. */
903 PUT_CODE (jump, NOTE);
904 NOTE_LINE_NUMBER (jump) = NOTE_INSN_DELETED;
905 NOTE_SOURCE_FILE (jump) = 0;
907 /* We only do this optimization if -O2, modifying the value of
908 r1 in the delay slot confuses debuggers and profilers on some
911 If we loose, we must use the non-delay form. This is unlikely
912 to ever happen. If it becomes a problem, claim that a call
913 has two delay slots and only the second can be filled with
916 The 88110 can lose when a jsr.n r1 is issued and a page fault
917 occurs accessing the delay slot. So don't use jsr.n form when
920 #ifdef AS_BUG_IMMEDIATE_LABEL /* The assembler restricts immediate values. */
922 || ! ADD_INTVAL (delta * 2)
925 || ! ADD_INTVAL (delta)
927 || (REG_P (addr) && REGNO (addr) == 1))
933 ? "bsr %0#plt\n\tbr %l1"
934 : "bsr %0\n\tbr %l1"));
937 /* Output the short branch form. */
938 output_asm_insn ((REG_P (addr)
940 : (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")),
945 ? "subu %#r1,%#r1,.-%l0+4"
946 : "addu %#r1,%#r1,%l0-.-4");
949 operands[0] = gen_label_rtx ();
950 operands[1] = gen_label_rtx ();
955 last = "subu %#r1,%#r1,%l0\n%l1:";
961 last = "addu %#r1,%#r1,%l0\n%l1:";
964 /* Record the values to be computed later as "def name,high-low". */
965 sb_name = gen_rtx_EXPR_LIST (VOIDmode, operands[0], sb_name);
966 sb_high = gen_rtx_EXPR_LIST (VOIDmode, high, sb_high);
967 sb_low = gen_rtx_EXPR_LIST (VOIDmode, low, sb_low);
968 #endif /* Don't USE_GAS */
975 : (flag_pic ? "bsr%. %0#plt" : "bsr%. %0"));
979 output_short_branch_defs (stream)
982 char name[256], high[256], low[256];
984 for (; sb_name && sb_high && sb_low;
985 sb_name = XEXP (sb_name, 1),
986 sb_high = XEXP (sb_high, 1),
987 sb_low = XEXP (sb_low, 1))
989 ASM_GENERATE_INTERNAL_LABEL
990 (name, "L", CODE_LABEL_NUMBER (XEXP (sb_name, 0)));
991 ASM_GENERATE_INTERNAL_LABEL
992 (high, "L", CODE_LABEL_NUMBER (XEXP (sb_high, 0)));
993 ASM_GENERATE_INTERNAL_LABEL
994 (low, "L", CODE_LABEL_NUMBER (XEXP (sb_low, 0)));
995 /* This will change as the assembler requirements become known. */
996 fprintf (stream, "%s%s,%s-%s\n",
997 SET_ASM_OP, &name[1], &high[1], &low[1]);
999 if (sb_name || sb_high || sb_low)
1003 /* Return truth value of the statement that this conditional branch is likely
1004 to fall through. CONDITION, is the condition that JUMP_INSN is testing. */
1007 mostly_false_jump (jump_insn, condition)
1008 rtx jump_insn, condition;
1010 rtx target_label = JUMP_LABEL (jump_insn);
1013 /* Much of this isn't computed unless we're optimizing. */
1017 /* Determine if one path or the other leads to a return. */
1018 for (insnt = NEXT_INSN (target_label);
1020 insnt = NEXT_INSN (insnt))
1022 if (GET_CODE (insnt) == JUMP_INSN)
1024 else if (GET_CODE (insnt) == INSN
1025 && GET_CODE (PATTERN (insnt)) == SEQUENCE
1026 && GET_CODE (XVECEXP (PATTERN (insnt), 0, 0)) == JUMP_INSN)
1028 insnt = XVECEXP (PATTERN (insnt), 0, 0);
1033 && (GET_CODE (PATTERN (insnt)) == RETURN
1034 || (GET_CODE (PATTERN (insnt)) == SET
1035 && GET_CODE (SET_SRC (PATTERN (insnt))) == REG
1036 && REGNO (SET_SRC (PATTERN (insnt))) == 1)))
1039 for (insnj = NEXT_INSN (jump_insn);
1041 insnj = NEXT_INSN (insnj))
1043 if (GET_CODE (insnj) == JUMP_INSN)
1045 else if (GET_CODE (insnj) == INSN
1046 && GET_CODE (PATTERN (insnj)) == SEQUENCE
1047 && GET_CODE (XVECEXP (PATTERN (insnj), 0, 0)) == JUMP_INSN)
1049 insnj = XVECEXP (PATTERN (insnj), 0, 0);
1054 && (GET_CODE (PATTERN (insnj)) == RETURN
1055 || (GET_CODE (PATTERN (insnj)) == SET
1056 && GET_CODE (SET_SRC (PATTERN (insnj))) == REG
1057 && REGNO (SET_SRC (PATTERN (insnj))) == 1)))
1060 /* Predict to not return. */
1061 if ((insnt == 0) != (insnj == 0))
1062 return (insnt == 0);
1064 /* Predict loops to loop. */
1065 for (insnt = PREV_INSN (target_label);
1066 insnt && GET_CODE (insnt) == NOTE;
1067 insnt = PREV_INSN (insnt))
1068 if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_END)
1070 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_BEG)
1072 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_CONT)
1075 /* Predict backward branches usually take. */
1077 insnj = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
1080 if (INSN_ADDRESSES (INSN_UID (insnj))
1081 > INSN_ADDRESSES (INSN_UID (target_label)))
1084 /* EQ tests are usually false and NE tests are usually true. Also,
1085 most quantities are positive, so we can make the appropriate guesses
1086 about signed comparisons against zero. Consider unsigned comparisons
1087 to be a range check and assume quantities to be in range. */
1088 switch (GET_CODE (condition))
1091 /* Unconditional branch. */
1100 case GTU: /* Must get casesi right at least. */
1101 if (XEXP (condition, 1) == const0_rtx)
1108 if (XEXP (condition, 1) == const0_rtx)
1118 /* Return true if the operand is a power of two and is a floating
1119 point type (to optimize division by power of two into multiplication). */
1122 real_power_of_2_operand (op, mode)
1124 enum machine_mode mode ATTRIBUTE_UNUSED;
1128 int i[sizeof (REAL_VALUE_TYPE) / sizeof (int)];
1129 struct { /* IEEE double precision format */
1131 unsigned exponent : 11;
1132 unsigned mantissa1 : 20;
1135 struct { /* IEEE double format to quick check */
1136 unsigned sign : 1; /* if it fits in a float */
1137 unsigned exponent1 : 4;
1138 unsigned exponent2 : 7;
1139 unsigned mantissa1 : 20;
1144 if (GET_MODE (op) != DFmode && GET_MODE (op) != SFmode)
1147 if (GET_CODE (op) != CONST_DOUBLE)
1150 u.i[0] = CONST_DOUBLE_LOW (op);
1151 u.i[1] = CONST_DOUBLE_HIGH (op);
1153 if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0 /* not a power of two */
1154 || u.s.exponent == 0 /* constant 0.0 */
1155 || u.s.exponent == 0x7ff /* NAN */
1156 || (u.s2.exponent1 != 0x8 && u.s2.exponent1 != 0x7))
1157 return 0; /* const won't fit in float */
1162 /* Make OP legitimate for mode MODE. Currently this only deals with DFmode
1163 operands, putting them in registers and making CONST_DOUBLE values
1164 SFmode where possible. */
1167 legitimize_operand (op, mode)
1169 enum machine_mode mode;
1173 union real_extract r;
1174 struct { /* IEEE double precision format */
1176 unsigned exponent : 11;
1177 unsigned mantissa1 : 20;
1180 struct { /* IEEE double format to quick check */
1181 unsigned sign : 1; /* if it fits in a float */
1182 unsigned exponent1 : 4;
1183 unsigned exponent2 : 7;
1184 unsigned mantissa1 : 20;
1189 if (GET_CODE (op) == REG || mode != DFmode)
1192 if (GET_CODE (op) == CONST_DOUBLE)
1194 memcpy (&u.r, &CONST_DOUBLE_LOW (op), sizeof u);
1195 if (u.d.exponent != 0x7ff /* NaN */
1196 && u.d.mantissa2 == 0 /* Mantissa fits */
1197 && (u.s.exponent1 == 0x8 || u.s.exponent1 == 0x7) /* Exponent fits */
1198 && (temp = simplify_unary_operation (FLOAT_TRUNCATE, SFmode,
1200 return gen_rtx_FLOAT_EXTEND (mode, force_reg (SFmode, temp));
1202 else if (register_operand (op, mode))
1205 return force_reg (mode, op);
1208 /* Return true if OP is a suitable input for a move insn. */
1211 move_operand (op, mode)
1213 enum machine_mode mode;
1215 if (register_operand (op, mode))
1217 if (GET_CODE (op) == CONST_INT)
1218 return (classify_integer (mode, INTVAL (op)) < m88k_oru_hi16);
1219 if (GET_MODE (op) != mode)
1221 if (GET_CODE (op) == SUBREG)
1222 op = SUBREG_REG (op);
1223 if (GET_CODE (op) != MEM)
1227 if (GET_CODE (op) == LO_SUM)
1228 return (REG_P (XEXP (op, 0))
1229 && symbolic_address_p (XEXP (op, 1)));
1230 return memory_address_p (mode, op);
1233 /* Return true if OP is suitable for a call insn. */
1236 call_address_operand (op, mode)
1238 enum machine_mode mode ATTRIBUTE_UNUSED;
1240 return (REG_P (op) || symbolic_address_p (op));
1243 /* Returns true if OP is either a symbol reference or a sum of a symbol
1244 reference and a constant. */
1247 symbolic_address_p (op)
1250 switch (GET_CODE (op))
1258 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1259 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1260 && GET_CODE (XEXP (op, 1)) == CONST_INT);
1267 /* Return true if OP is a register or const0_rtx. */
1270 reg_or_0_operand (op, mode)
1272 enum machine_mode mode;
1274 return (op == const0_rtx || register_operand (op, mode));
1277 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
1280 arith_operand (op, mode)
1282 enum machine_mode mode;
1284 return (register_operand (op, mode)
1285 || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
1288 /* Return true if OP is a register or 5 bit integer. */
1291 arith5_operand (op, mode)
1293 enum machine_mode mode;
1295 return (register_operand (op, mode)
1296 || (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32));
1300 arith32_operand (op, mode)
1302 enum machine_mode mode;
1304 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
1308 arith64_operand (op, mode)
1310 enum machine_mode mode;
1312 return (register_operand (op, mode)
1313 || GET_CODE (op) == CONST_INT
1314 || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode));
1318 int5_operand (op, mode)
1320 enum machine_mode mode ATTRIBUTE_UNUSED;
1322 return (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32);
1326 int32_operand (op, mode)
1328 enum machine_mode mode ATTRIBUTE_UNUSED;
1330 return (GET_CODE (op) == CONST_INT);
1333 /* Return true if OP is a register or a valid immediate operand for
1337 add_operand (op, mode)
1339 enum machine_mode mode;
1341 return (register_operand (op, mode)
1342 || (GET_CODE (op) == CONST_INT && ADD_INT (op)));
1345 /* Nonzero if this is a bitmask filling the bottom bits, for optimizing and +
1346 shift left combinations into a single mak instruction. */
1352 return (value && POWER_OF_2_or_0 (value + 1));
1356 reg_or_bbx_mask_operand (op, mode)
1358 enum machine_mode mode;
1361 if (register_operand (op, mode))
1363 if (GET_CODE (op) != CONST_INT)
1366 value = INTVAL (op);
1367 if (POWER_OF_2 (value))
1373 /* Return true if OP is valid to use in the context of a floating
1374 point operation. Special case 0.0, since we can use r0. */
1377 real_or_0_operand (op, mode)
1379 enum machine_mode mode;
1381 if (mode != SFmode && mode != DFmode)
1384 return (register_operand (op, mode)
1385 || (GET_CODE (op) == CONST_DOUBLE
1386 && op == CONST0_RTX (mode)));
1389 /* Return true if OP is valid to use in the context of logic arithmetic
1390 on condition codes. */
1393 partial_ccmode_register_operand (op, mode)
1395 enum machine_mode mode ATTRIBUTE_UNUSED;
1397 return register_operand (op, CCmode) || register_operand (op, CCEVENmode);
1400 /* Return true if OP is a relational operator. */
1405 enum machine_mode mode ATTRIBUTE_UNUSED;
1407 switch (GET_CODE (op))
1426 even_relop (op, mode)
1428 enum machine_mode mode ATTRIBUTE_UNUSED;
1430 switch (GET_CODE (op))
1444 odd_relop (op, mode)
1446 enum machine_mode mode ATTRIBUTE_UNUSED;
1448 switch (GET_CODE (op))
1461 /* Return true if OP is a relational operator, and is not an unsigned
1462 relational operator. */
1465 relop_no_unsigned (op, mode)
1467 enum machine_mode mode ATTRIBUTE_UNUSED;
1469 switch (GET_CODE (op))
1477 /* @@ What is this test doing? Why not use `mode'? */
1478 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
1479 || GET_MODE (op) == DImode
1480 || GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_FLOAT
1481 || GET_MODE (XEXP (op, 0)) == DImode
1482 || GET_MODE_CLASS (GET_MODE (XEXP (op, 1))) == MODE_FLOAT
1483 || GET_MODE (XEXP (op, 1)) == DImode)
1491 /* Return true if the code of this rtx pattern is EQ or NE. */
1494 equality_op (op, mode)
1496 enum machine_mode mode ATTRIBUTE_UNUSED;
1498 return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
1501 /* Return true if the code of this rtx pattern is pc or label_ref. */
1504 pc_or_label_ref (op, mode)
1506 enum machine_mode mode ATTRIBUTE_UNUSED;
1508 return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF);
1511 /* Output to FILE the start of the assembler file. */
1513 /* This definition must match lang_independent_options from toplev.c. */
1514 struct m88k_lang_independent_options
1516 const char *const string;
1517 int *const variable;
1519 const char *const description;
1522 static void output_options PARAMS ((FILE *,
1523 const struct m88k_lang_independent_options *,
1525 const struct m88k_lang_independent_options *,
1526 int, int, int, const char *, const char *,
1530 output_option (file, sep, type, name, indent, pos, max)
1539 if ((long)(strlen (sep) + strlen (type) + strlen (name) + pos) > max)
1541 fprintf (file, indent);
1542 return fprintf (file, "%s%s", type, name);
1544 return pos + fprintf (file, "%s%s%s", sep, type, name);
1547 static const struct { const char *const name; const int value; } m_options[] =
1551 output_options (file, f_options, f_len, W_options, W_len,
1552 pos, max, sep, indent, term)
1554 const struct m88k_lang_independent_options *f_options;
1555 const struct m88k_lang_independent_options *W_options;
1566 pos = output_option (file, sep, "-O", "", indent, pos, max);
1567 if (write_symbols != NO_DEBUG)
1568 pos = output_option (file, sep, "-g", "", indent, pos, max);
1570 pos = output_option (file, sep, "-p", "", indent, pos, max);
1571 for (j = 0; j < f_len; j++)
1572 if (*f_options[j].variable == f_options[j].on_value)
1573 pos = output_option (file, sep, "-f", f_options[j].string,
1576 for (j = 0; j < W_len; j++)
1577 if (*W_options[j].variable == W_options[j].on_value)
1578 pos = output_option (file, sep, "-W", W_options[j].string,
1581 for (j = 0; j < (long) ARRAY_SIZE (m_options); j++)
1582 if (m_options[j].name[0] != '\0'
1583 && m_options[j].value > 0
1584 && ((m_options[j].value & target_flags)
1585 == m_options[j].value))
1586 pos = output_option (file, sep, "-m", m_options[j].name,
1589 if (m88k_short_data)
1590 pos = output_option (file, sep, "-mshort-data-", m88k_short_data,
1593 fprintf (file, term);
1597 output_file_start (file, f_options, f_len, W_options, W_len)
1599 const struct m88k_lang_independent_options *f_options;
1600 const struct m88k_lang_independent_options *W_options;
1605 ASM_FIRST_LINE (file);
1608 fprintf (file, "%s\n", REQUIRES_88110_ASM_OP);
1609 output_file_directive (file, main_input_filename);
1610 /* Switch to the data section so that the coffsem symbol
1611 isn't in the text section. */
1614 if (TARGET_IDENTIFY_REVISION)
1618 time_t now = time ((time_t *)0);
1619 sprintf (indent, "]\"\n%s\"@(#)%s [", IDENT_ASM_OP, main_input_filename);
1620 fprintf (file, indent+3);
1621 pos = fprintf (file, "gcc %s, %.24s,", version_string, ctime (&now));
1623 /* ??? It would be nice to call print_switch_values here (and thereby
1624 let us delete output_options) but this is kept in until it is known
1625 whether the change in content format matters. */
1626 output_options (file, f_options, f_len, W_options, W_len,
1627 pos, 150 - strlen (indent), " ", indent, "]\"\n\n");
1629 fprintf (file, "]\"\n");
1630 print_switch_values (file, 0, 150 - strlen (indent),
1631 indent + 3, " ", "]\"\n");
1636 /* Output an ascii string. */
1639 output_ascii (file, opcode, max, p, size)
1649 register int num = 0;
1651 fprintf (file, "%s\"", opcode);
1652 for (i = 0; i < size; i++)
1654 register int c = (unsigned char) p[i];
1658 fprintf (file, "\"\n%s\"", opcode);
1662 if (c == '\"' || c == '\\')
1670 else if (in_escape && ISDIGIT (c))
1672 /* If a digit follows an octal-escape, the VAX assembler fails
1673 to stop reading the escape after three digits. Continue to
1674 output the values as an octal-escape until a non-digit is
1676 fprintf (file, "\\%03o", c);
1679 else if ((c >= ' ' && c < 0177) || (c == '\t'))
1689 /* Some assemblers can't handle \a, \v, or \?. */
1690 case '\f': c = 'f'; goto escape;
1691 case '\b': c = 'b'; goto escape;
1692 case '\r': c = 'r'; goto escape;
1693 case '\n': c = 'n'; goto escape;
1696 fprintf (file, "\\%03o", c);
1701 fprintf (file, "\"\n");
1704 /* Output a label (allows insn-output.c to be compiled without including
1705 m88k.c or needing to include stdio.h). */
1708 output_label (label_number)
1711 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", label_number);
1714 /* Generate the assembly code for function entry.
1716 The prologue is responsible for setting up the stack frame,
1717 initializing the frame pointer register, saving registers that must be
1718 saved, and allocating SIZE additional bytes of storage for the
1719 local variables. SIZE is an integer. FILE is a stdio
1720 stream to which the assembler code should be output.
1722 The label for the beginning of the function need not be output by this
1723 macro. That has already been done when the macro is run.
1725 To determine which registers to save, the macro can refer to the array
1726 `regs_ever_live': element R is nonzero if hard register
1727 R is used anywhere within the function. This implies the
1728 function prologue should save register R, but not if it is one
1729 of the call-used registers.
1731 On machines where functions may or may not have frame-pointers, the
1732 function entry code must vary accordingly; it must set up the frame
1733 pointer if one is wanted, and not otherwise. To determine whether a
1734 frame pointer is in wanted, the macro can refer to the variable
1735 `frame_pointer_needed'. The variable's value will be 1 at run
1736 time in a function that needs a frame pointer.
1738 On machines where an argument may be passed partly in registers and
1739 partly in memory, this macro must examine the variable
1740 `current_function_pretend_args_size', and allocate that many bytes
1741 of uninitialized space on the stack just underneath the first argument
1742 arriving on the stack. (This may not be at the very end of the stack,
1743 if the calling sequence has pushed anything else since pushing the stack
1744 arguments. But usually, on such machines, nothing else has been pushed
1745 yet, because the function prologue itself does all the pushing.)
1747 If `ACCUMULATE_OUTGOING_ARGS' is defined, the variable
1748 `current_function_outgoing_args_size' contains the size in bytes
1749 required for the outgoing arguments. This macro must add that
1750 amount of uninitialized space to very bottom of the stack.
1752 The stack frame we use looks like this:
1755 |==============================================|
1757 |==============================================|
1758 | [caller's outgoing memory arguments] |
1759 |==============================================|
1760 | caller's outgoing argument area (32 bytes) |
1761 sp -> |==============================================| <- ap
1762 | [local variable space] |
1763 |----------------------------------------------|
1764 | [return address (r1)] |
1765 |----------------------------------------------|
1766 | [previous frame pointer (r30)] |
1767 |==============================================| <- fp
1768 | [preserved registers (r25..r14)] |
1769 |----------------------------------------------|
1770 | [preserved registers (x29..x22)] |
1771 |==============================================|
1772 | [dynamically allocated space (alloca)] |
1773 |==============================================|
1774 | [callee's outgoing memory arguments] |
1775 |==============================================|
1776 | [callee's outgoing argument area (32 bytes)] |
1777 |==============================================| <- sp
1781 r1 and r30 must be saved if debugging.
1783 fp (if present) is located two words down from the local
1787 static void emit_add PARAMS ((rtx, rtx, int));
1788 static void preserve_registers PARAMS ((int, int));
1789 static void emit_ldst PARAMS ((int, int, enum machine_mode, int));
1790 static void output_tdesc PARAMS ((FILE *, int));
1791 static int uses_arg_area_p PARAMS ((void));
1795 static char save_regs[FIRST_PSEUDO_REGISTER];
1796 static int frame_laid_out;
1797 static int frame_size;
1798 static int variable_args_p;
1799 static int epilogue_marked;
1800 static int prologue_marked;
1802 #define FIRST_OCS_PRESERVE_REGISTER 14
1803 #define LAST_OCS_PRESERVE_REGISTER 30
1805 #define FIRST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 22)
1806 #define LAST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 31)
1808 #define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
1809 #define ROUND_CALL_BLOCK_SIZE(BYTES) \
1810 (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
1812 /* Establish the position of the FP relative to the SP. This is done
1813 either during output_function_prologue() or by
1814 INITIAL_ELIMINATION_OFFSET. */
1817 m88k_layout_frame ()
1823 memset ((char *) &save_regs[0], 0, sizeof (save_regs));
1824 sp_size = nregs = nxregs = 0;
1825 frame_size = get_frame_size ();
1827 /* Since profiling requires a call, make sure r1 is saved. */
1828 if (current_function_profile)
1831 /* If we are producing debug information, store r1 and r30 where the
1832 debugger wants to find them (r30 at r30+0, r1 at r30+4). Space has
1833 already been reserved for r1/r30 in STARTING_FRAME_OFFSET. */
1834 if (write_symbols != NO_DEBUG && !TARGET_OCS_FRAME_POSITION)
1837 /* If there is a call, alloca is used, __builtin_alloca is used, or
1838 a dynamic-sized object is defined, add the 8 additional words
1839 for the callee's argument area. The common denominator is that the
1840 FP is required. may_call_alloca only gets calls to alloca;
1841 current_function_calls_alloca gets alloca and __builtin_alloca. */
1842 if (regs_ever_live[1] || frame_pointer_needed)
1845 sp_size += REG_PARM_STACK_SPACE (0);
1848 /* If we are producing PIC, save the addressing base register and r1. */
1849 if (flag_pic && current_function_uses_pic_offset_table)
1851 save_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
1855 /* If a frame is requested, save the previous FP, and the return
1856 address (r1), so that a traceback can be done without using tdesc
1857 information. Otherwise, simply save the FP if it is used as
1858 a preserve register. */
1859 if (frame_pointer_needed)
1860 save_regs[FRAME_POINTER_REGNUM] = save_regs[1] = 1;
1861 else if (regs_ever_live[FRAME_POINTER_REGNUM])
1862 save_regs[FRAME_POINTER_REGNUM] = 1;
1864 /* Figure out which extended register(s) needs to be saved. */
1865 for (regno = FIRST_EXTENDED_REGISTER + 1; regno < FIRST_PSEUDO_REGISTER;
1867 if (regs_ever_live[regno] && ! call_used_regs[regno])
1869 save_regs[regno] = 1;
1873 /* Figure out which normal register(s) needs to be saved. */
1874 for (regno = 2; regno < FRAME_POINTER_REGNUM; regno++)
1875 if (regs_ever_live[regno] && ! call_used_regs[regno])
1877 save_regs[regno] = 1;
1881 /* Achieve greatest use of double memory ops. Either we end up saving
1882 r30 or we use that slot to align the registers we do save. */
1883 if (nregs >= 2 && save_regs[1] && !save_regs[FRAME_POINTER_REGNUM])
1886 nregs += save_regs[1] + save_regs[FRAME_POINTER_REGNUM];
1887 /* if we need to align extended registers, add a word */
1888 if (nxregs > 0 && (nregs & 1) != 0)
1890 sp_size += 4 * nregs;
1891 sp_size += 8 * nxregs;
1892 sp_size += current_function_outgoing_args_size;
1894 /* The first two saved registers are placed above the new frame pointer
1895 if any. In the only case this matters, they are r1 and r30. */
1896 if (frame_pointer_needed || sp_size)
1897 m88k_fp_offset = ROUND_CALL_BLOCK_SIZE (sp_size - STARTING_FRAME_OFFSET);
1899 m88k_fp_offset = -STARTING_FRAME_OFFSET;
1900 m88k_stack_size = m88k_fp_offset + STARTING_FRAME_OFFSET;
1902 /* First, combine m88k_stack_size and size. If m88k_stack_size is
1903 non-zero, align the frame size to 8 mod 16; otherwise align the
1904 frame size to 0 mod 16. (If stacks are 8 byte aligned, this ends
1908 = ((m88k_stack_size ? STACK_UNIT_BOUNDARY - STARTING_FRAME_OFFSET : 0)
1909 - (frame_size % STACK_UNIT_BOUNDARY));
1911 need += STACK_UNIT_BOUNDARY;
1913 = ROUND_CALL_BLOCK_SIZE (m88k_stack_size + frame_size + need
1914 + current_function_pretend_args_size);
1918 /* Return true if this function is known to have a null prologue. */
1923 if (! reload_completed)
1925 if (! frame_laid_out)
1926 m88k_layout_frame ();
1927 return (! frame_pointer_needed
1930 && m88k_stack_size == 0);
1933 /* Determine if the current function has any references to the arg pointer.
1934 This is done indirectly by examining the DECL_ARGUMENTS' DECL_RTL.
1935 It is OK to return TRUE if there are no references, but FALSE must be
1943 if (current_function_decl == 0
1944 || current_function_varargs
1948 for (parm = DECL_ARGUMENTS (current_function_decl);
1950 parm = TREE_CHAIN (parm))
1952 if (DECL_RTL (parm) == 0
1953 || GET_CODE (DECL_RTL (parm)) == MEM)
1956 if (DECL_INCOMING_RTL (parm) == 0
1957 || GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
1964 m88k_output_function_prologue (stream, size)
1965 FILE *stream ATTRIBUTE_UNUSED;
1966 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
1968 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! quiet_flag && leaf_function_p ())
1969 fprintf (stderr, "$");
1971 m88k_prologue_done = 1; /* it's ok now to put out ln directives */
1975 m88k_output_function_end_prologue (stream)
1978 if (TARGET_OCS_DEBUG_INFO && !prologue_marked)
1980 PUT_OCS_FUNCTION_START (stream);
1981 prologue_marked = 1;
1983 /* If we've already passed the start of the epilogue, say that
1984 it starts here. This marks the function as having a null body,
1985 but at a point where the return address is in a known location.
1987 Originally, I thought this couldn't happen, but the pic prologue
1988 for leaf functions ends with the instruction that restores the
1989 return address from the temporary register. If the temporary
1990 register is never used, that instruction can float all the way
1991 to the end of the function. */
1992 if (epilogue_marked)
1993 PUT_OCS_FUNCTION_END (stream);
1998 m88k_expand_prologue ()
2000 m88k_layout_frame ();
2002 if (TARGET_OPTIMIZE_ARG_AREA
2004 && ! uses_arg_area_p ())
2006 /* The incoming argument area is used for stack space if it is not
2007 used (or if -mno-optimize-arg-area is given). */
2008 if ((m88k_stack_size -= REG_PARM_STACK_SPACE (0)) < 0)
2009 m88k_stack_size = 0;
2012 if (m88k_stack_size)
2013 emit_add (stack_pointer_rtx, stack_pointer_rtx, -m88k_stack_size);
2015 if (nregs || nxregs)
2016 preserve_registers (m88k_fp_offset + 4, 1);
2018 if (frame_pointer_needed)
2019 emit_add (frame_pointer_rtx, stack_pointer_rtx, m88k_fp_offset);
2021 if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM])
2023 rtx return_reg = gen_rtx_REG (SImode, 1);
2024 rtx label = gen_label_rtx ();
2025 rtx temp_reg = NULL_RTX;
2029 temp_reg = gen_rtx_REG (SImode, TEMP_REGNUM);
2030 emit_move_insn (temp_reg, return_reg);
2032 emit_insn (gen_locate1 (pic_offset_table_rtx, label));
2033 emit_insn (gen_locate2 (pic_offset_table_rtx, label));
2034 emit_insn (gen_addsi3 (pic_offset_table_rtx,
2035 pic_offset_table_rtx, return_reg));
2037 emit_move_insn (return_reg, temp_reg);
2039 if (current_function_profile)
2040 emit_insn (gen_blockage ());
2043 /* This function generates the assembly code for function exit,
2044 on machines that need it.
2046 The function epilogue should not depend on the current stack pointer!
2047 It should use the frame pointer only, if there is a frame pointer.
2048 This is mandatory because of alloca; we also take advantage of it to
2049 omit stack adjustments before returning. */
2052 m88k_output_function_begin_epilogue (stream)
2055 if (TARGET_OCS_DEBUG_INFO && !epilogue_marked && prologue_marked)
2057 PUT_OCS_FUNCTION_END (stream);
2059 epilogue_marked = 1;
2063 m88k_output_function_epilogue (stream, size)
2065 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
2067 rtx insn = get_last_insn ();
2069 if (TARGET_OCS_DEBUG_INFO && !epilogue_marked)
2070 PUT_OCS_FUNCTION_END (stream);
2072 /* If the last insn isn't a BARRIER, we must write a return insn. This
2073 should only happen if the function has no prologue and no body. */
2074 if (GET_CODE (insn) == NOTE)
2075 insn = prev_nonnote_insn (insn);
2076 if (insn == 0 || GET_CODE (insn) != BARRIER)
2077 fprintf (stream, "\tjmp\t %s\n", reg_names[1]);
2079 /* If the last insn is a barrier, and the insn before that is a call,
2080 then add a nop instruction so that tdesc can walk the stack correctly
2081 even though there is no epilogue. (Otherwise, the label for the
2082 end of the tdesc region ends up at the start of the next function. */
2083 if (insn && GET_CODE (insn) == BARRIER)
2085 insn = prev_nonnote_insn (insn);
2086 if (insn && GET_CODE (insn) == CALL_INSN)
2087 fprintf (stream, "\tor\t %s,%s,%s\n",reg_names[0],reg_names[0],reg_names[0]);
2090 output_short_branch_defs (stream);
2092 fprintf (stream, "\n");
2094 if (TARGET_OCS_DEBUG_INFO)
2095 output_tdesc (stream, m88k_fp_offset + 4);
2097 m88k_function_number++;
2098 m88k_prologue_done = 0; /* don't put out ln directives */
2099 variable_args_p = 0; /* has variable args */
2101 epilogue_marked = 0;
2102 prologue_marked = 0;
2106 m88k_expand_epilogue ()
2108 #if (MONITOR_GCC & 0x4) /* What are interesting prologue/epilogue values? */
2109 fprintf (stream, "; size = %d, m88k_fp_offset = %d, m88k_stack_size = %d\n",
2110 size, m88k_fp_offset, m88k_stack_size);
2113 if (frame_pointer_needed)
2114 emit_add (stack_pointer_rtx, frame_pointer_rtx, -m88k_fp_offset);
2116 if (nregs || nxregs)
2117 preserve_registers (m88k_fp_offset + 4, 0);
2119 if (m88k_stack_size)
2120 emit_add (stack_pointer_rtx, stack_pointer_rtx, m88k_stack_size);
2123 /* Emit insns to set DSTREG to SRCREG + AMOUNT during the prologue or
2127 emit_add (dstreg, srcreg, amount)
2132 rtx incr = GEN_INT (abs (amount));
2134 if (! ADD_INTVAL (amount))
2136 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
2137 emit_move_insn (temp, incr);
2140 emit_insn ((amount < 0 ? gen_subsi3 : gen_addsi3) (dstreg, srcreg, incr));
2143 /* Save/restore the preserve registers. base is the highest offset from
2144 r31 at which a register is stored. store_p is true if stores are to
2145 be done; otherwise loads. */
2148 preserve_registers (base, store_p)
2157 } mem_op[FIRST_PSEUDO_REGISTER];
2158 struct mem_op *mo_ptr = mem_op;
2160 /* The 88open OCS mandates that preserved registers be stored in
2161 increasing order. For compatibility with current practice,
2162 the order is r1, r30, then the preserve registers. */
2167 /* An extra word is given in this case to make best use of double
2169 if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM])
2171 emit_ldst (store_p, 1, SImode, offset);
2176 /* Walk the registers to save recording all single memory operations. */
2177 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2178 if (save_regs[regno])
2180 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2183 mo_ptr->regno = regno;
2184 mo_ptr->offset = offset;
2195 /* Walk the registers to save recording all double memory operations.
2196 This avoids a delay in the epilogue (ld.d/ld). */
2198 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2199 if (save_regs[regno])
2201 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2208 mo_ptr->regno = regno-1;
2209 mo_ptr->offset = offset-4;
2216 /* Walk the extended registers to record all memory operations. */
2217 /* Be sure the offset is double word aligned. */
2218 offset = (offset - 1) & ~7;
2219 for (regno = FIRST_PSEUDO_REGISTER - 1; regno > FIRST_EXTENDED_REGISTER;
2221 if (save_regs[regno])
2224 mo_ptr->regno = regno;
2225 mo_ptr->offset = offset;
2232 /* Output the memory operations. */
2233 for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++)
2236 emit_ldst (store_p, mo_ptr->regno,
2237 (mo_ptr->nregs > 1 ? DImode : SImode),
2243 emit_ldst (store_p, regno, mode, offset)
2246 enum machine_mode mode;
2249 rtx reg = gen_rtx_REG (mode, regno);
2252 if (SMALL_INTVAL (offset))
2254 mem = gen_rtx_MEM (mode, plus_constant (stack_pointer_rtx, offset));
2258 /* offset is too large for immediate index must use register */
2260 rtx disp = GEN_INT (offset);
2261 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
2262 rtx regi = gen_rtx_PLUS (SImode, stack_pointer_rtx, temp);
2264 emit_move_insn (temp, disp);
2265 mem = gen_rtx_MEM (mode, regi);
2269 emit_move_insn (mem, reg);
2271 emit_move_insn (reg, mem);
2274 /* Convert the address expression REG to a CFA offset. */
2277 m88k_debugger_offset (reg, offset)
2279 register int offset;
2281 if (GET_CODE (reg) == PLUS)
2283 offset = INTVAL (XEXP (reg, 1));
2284 reg = XEXP (reg, 0);
2287 /* Put the offset in terms of the CFA (arg pointer). */
2288 if (reg == frame_pointer_rtx)
2289 offset += m88k_fp_offset - m88k_stack_size;
2290 else if (reg == stack_pointer_rtx)
2291 offset -= m88k_stack_size;
2292 else if (reg != arg_pointer_rtx)
2294 #if (MONITOR_GCC & 0x10) /* Watch for suspicious symbolic locations. */
2295 if (! (GET_CODE (reg) == REG
2296 && REGNO (reg) >= FIRST_PSEUDO_REGISTER))
2297 warning ("internal gcc error: Can't express symbolic location");
2305 /* Output the 88open OCS proscribed text description information.
2308 0 22: info-byte-length (16 or 20 bytes)
2309 0 2: info-alignment (word 2)
2310 1 32: info-protocol (version 1 or 2(pic))
2311 2 32: starting-address (inclusive, not counting prologue)
2312 3 32: ending-address (exclusive, not counting epilog)
2313 4 8: info-variant (version 1 or 3(extended registers))
2314 4 17: register-save-mask (from register 14 to 30)
2316 4 1: return-address-info-discriminant
2317 4 5: frame-address-register
2318 5 32: frame-address-offset
2319 6 32: return-address-info
2320 7 32: register-save-offset
2321 8 16: extended-register-save-mask (x16 - x31)
2322 8 16: extended-register-save-offset (WORDS from register-save-offset) */
2325 output_tdesc (file, offset)
2330 long mask, return_address_info, register_save_offset;
2331 long xmask, xregister_save_offset;
2334 for (mask = 0, i = 0, regno = FIRST_OCS_PRESERVE_REGISTER;
2335 regno <= LAST_OCS_PRESERVE_REGISTER;
2339 if (save_regs[regno])
2346 for (xmask = 0, j = 0, regno = FIRST_OCS_EXTENDED_PRESERVE_REGISTER;
2347 regno <= LAST_OCS_EXTENDED_PRESERVE_REGISTER;
2351 if (save_regs[regno])
2360 if ((nxregs > 0 || nregs > 2) && !save_regs[FRAME_POINTER_REGNUM])
2362 return_address_info = - m88k_stack_size + offset;
2363 register_save_offset = return_address_info - i*4;
2367 return_address_info = 1;
2368 register_save_offset = - m88k_stack_size + offset + 4 - i*4;
2371 xregister_save_offset = - (j * 2 + ((register_save_offset >> 2) & 1));
2375 /* 8:0,22:(20 or 16),2:2 */
2376 fprintf (file, "%s%d,%d", integer_asm_op (4, TRUE),
2377 (((xmask != 0) ? 20 : 16) << 2) | 2,
2380 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_START_PREFIX, m88k_function_number);
2381 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2382 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_END_PREFIX, m88k_function_number);
2383 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2385 fprintf (file, ",0x%x,0x%x,0x%lx,0x%lx",
2386 /* 8:1,17:0x%.3x,1:0,1:%d,5:%d */
2387 (int)(((xmask ? 3 : 1) << (17+1+1+5))
2389 | ((!!save_regs[1]) << 5)
2390 | (frame_pointer_needed
2391 ? FRAME_POINTER_REGNUM
2392 : STACK_POINTER_REGNUM)),
2393 (m88k_stack_size - (frame_pointer_needed ? m88k_fp_offset : 0)),
2394 return_address_info,
2395 register_save_offset);
2397 fprintf (file, ",0x%lx%04lx", xmask, (0xffff & xregister_save_offset));
2403 /* Output assembler code to FILE to increment profiler label # LABELNO
2404 for profiling a function entry. NAME is the mcount function name
2405 (varies), SAVEP indicates whether the parameter registers need to
2406 be saved and restored. */
2409 output_function_profiler (file, labelno, name, savep)
2417 const char *const temp = (savep ? reg_names[2] : reg_names[10]);
2419 /* Remember to update FUNCTION_PROFILER_LENGTH. */
2423 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2424 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2425 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2426 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2427 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2430 ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno);
2433 fprintf (file, "\tor.u\t %s,%s,%shi16(%s#got_rel)\n",
2434 temp, reg_names[0], m88k_pound_sign, &label[1]);
2435 fprintf (file, "\tor\t %s,%s,%slo16(%s#got_rel)\n",
2436 temp, temp, m88k_pound_sign, &label[1]);
2437 sprintf (dbi, "\tld\t %s,%s,%s\n", temp,
2438 reg_names[PIC_OFFSET_TABLE_REGNUM], temp);
2442 sprintf (dbi, "\tld\t %s,%s,%s#got_rel\n", temp,
2443 reg_names[PIC_OFFSET_TABLE_REGNUM], &label[1]);
2447 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n",
2448 temp, reg_names[0], m88k_pound_sign, &label[1]);
2449 sprintf (dbi, "\tor\t %s,%s,%slo16(%s)\n",
2450 temp, temp, m88k_pound_sign, &label[1]);
2454 fprintf (file, "\tbsr.n\t %s#plt\n", name);
2456 fprintf (file, "\tbsr.n\t %s\n", name);
2461 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2462 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2463 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2464 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2465 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2469 /* Output assembler code to FILE to initialize basic-block profiling for
2470 the current module. LABELNO is unique to each instance. */
2473 output_function_block_profiler (file, labelno)
2480 /* Remember to update FUNCTION_BLOCK_PROFILER_LENGTH. */
2482 ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 0);
2483 ASM_GENERATE_INTERNAL_LABEL (label, "LPY", labelno);
2485 /* @@ Need to deal with PIC. I'm not sure what the requirements are on
2486 register usage, so I used r26/r27 to be safe. */
2487 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n", reg_names[27], reg_names[0],
2488 m88k_pound_sign, &block[1]);
2489 fprintf (file, "\tld\t %s,%s,%slo16(%s)\n", reg_names[26], reg_names[27],
2490 m88k_pound_sign, &block[1]);
2491 fprintf (file, "\tbcnd\t %sne0,%s,%s\n",
2492 m88k_pound_sign, reg_names[26], &label[1]);
2493 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2494 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2495 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2496 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2497 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2498 fputs ("\tbsr.n\t ", file);
2499 ASM_OUTPUT_LABELREF (file, "__bb_init_func");
2501 fprintf (file, "\tor\t %s,%s,%slo16(%s)\n", reg_names[2], reg_names[27],
2502 m88k_pound_sign, &block[1]);
2503 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2504 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2505 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2506 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2507 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2508 ASM_OUTPUT_INTERNAL_LABEL (file, "LPY", labelno);
2511 /* Output assembler code to FILE to increment the count associated with
2512 the basic block number BLOCKNO. */
2515 output_block_profiler (file, blockno)
2521 /* Remember to update BLOCK_PROFILER_LENGTH. */
2523 ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 2);
2525 /* @@ Need to deal with PIC. I'm not sure what the requirements are on
2526 register usage, so I used r26/r27 to be safe. */
2527 fprintf (file, "\tor.u\t %s,%s,%shi16(%s+%d)\n", reg_names[27], reg_names[0],
2528 m88k_pound_sign, &block[1], 4 * blockno);
2529 fprintf (file, "\tld\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27],
2530 m88k_pound_sign, &block[1], 4 * blockno);
2531 fprintf (file, "\taddu\t %s,%s,1\n", reg_names[26], reg_names[26]);
2532 fprintf (file, "\tst\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27],
2533 m88k_pound_sign, &block[1], 4 * blockno);
2536 /* Determine whether a function argument is passed in a register, and
2539 The arguments are CUM, which summarizes all the previous
2540 arguments; MODE, the machine mode of the argument; TYPE,
2541 the data type of the argument as a tree node or 0 if that is not known
2542 (which happens for C support library functions); and NAMED,
2543 which is 1 for an ordinary argument and 0 for nameless arguments that
2544 correspond to `...' in the called function's prototype.
2546 The value of the expression should either be a `reg' RTX for the
2547 hard register in which to pass the argument, or zero to pass the
2548 argument on the stack.
2550 On the m88000 the first eight words of args are normally in registers
2551 and the rest are pushed. Double precision floating point must be
2552 double word aligned (and if in a register, starting on an even
2553 register). Structures and unions which are not 4 byte, and word
2554 aligned are passed in memory rather than registers, even if they
2555 would fit completely in the registers under OCS rules.
2557 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2558 For structures that are passed in memory, but could have been
2559 passed in registers, we first load the structure into the
2560 register, and then when the last argument is passed, we store
2561 the registers into the stack locations. This fixes some bugs
2562 where GCC did not expect to have register arguments, followed
2563 by stack arguments, followed by register arguments. */
2566 m88k_function_arg (args_so_far, mode, type, named)
2567 CUMULATIVE_ARGS args_so_far;
2568 enum machine_mode mode;
2570 int named ATTRIBUTE_UNUSED;
2574 if (type != 0 /* undo putting struct in register */
2575 && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
2578 if (mode == BLKmode && TARGET_WARN_PASS_STRUCT)
2579 warning ("argument #%d is a structure", args_so_far + 1);
2581 if ((args_so_far & 1) != 0
2582 && (mode == DImode || mode == DFmode
2583 || (type != 0 && TYPE_ALIGN (type) > 32)))
2588 return (rtx) 0; /* don't put args in registers */
2591 if (type == 0 && mode == BLKmode)
2592 abort (); /* m88k_function_arg argument `type' is NULL for BLKmode. */
2594 bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
2595 words = (bytes + 3) / 4;
2597 if (args_so_far + words > 8)
2598 return (rtx) 0; /* args have exhausted registers */
2600 else if (mode == BLKmode
2601 && (TYPE_ALIGN (type) != BITS_PER_WORD
2602 || bytes != UNITS_PER_WORD))
2605 return gen_rtx_REG (((mode == BLKmode) ? TYPE_MODE (type) : mode),
2609 /* Do what is necessary for `va_start'. We look at the current function
2610 to determine if stdargs or varargs is used and spill as necessary.
2611 We return a pointer to the spill area. */
2614 m88k_builtin_saveregs ()
2617 tree fntype = TREE_TYPE (current_function_decl);
2618 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2619 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2620 != void_type_node)))
2621 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
2624 variable_args_p = 1;
2627 if (GET_CODE (current_function_arg_offset_rtx) == CONST_INT)
2628 fixed = ((INTVAL (current_function_arg_offset_rtx) + argadj)
2631 /* Allocate the register space, and store it as the __va_reg member. */
2632 addr = assign_stack_local (BLKmode, 8 * UNITS_PER_WORD, -1);
2633 set_mem_alias_set (addr, get_varargs_alias_set ());
2634 RTX_UNCHANGING_P (addr) = 1;
2635 RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
2637 /* Now store the incoming registers. */
2639 move_block_from_reg (2 + fixed,
2640 adjust_address (addr, Pmode, fixed * UNITS_PER_WORD),
2642 UNITS_PER_WORD * (8 - fixed));
2644 /* Return the address of the save area, but don't put it in a
2645 register. This fails when not optimizing and produces worse code
2647 return XEXP (addr, 0);
2650 /* Define the `__builtin_va_list' type for the ABI. */
2653 m88k_build_va_list ()
2655 tree field_reg, field_stk, field_arg, int_ptr_type_node, record;
2657 int_ptr_type_node = build_pointer_type (integer_type_node);
2659 record = make_node (RECORD_TYPE);
2661 field_arg = build_decl (FIELD_DECL, get_identifier ("__va_arg"),
2663 field_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"),
2665 field_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),
2668 DECL_FIELD_CONTEXT (field_arg) = record;
2669 DECL_FIELD_CONTEXT (field_stk) = record;
2670 DECL_FIELD_CONTEXT (field_reg) = record;
2672 TYPE_FIELDS (record) = field_arg;
2673 TREE_CHAIN (field_arg) = field_stk;
2674 TREE_CHAIN (field_stk) = field_reg;
2676 layout_type (record);
2680 /* Implement `va_start' for varargs and stdarg. */
2683 m88k_va_start (stdarg_p, valist, nextarg)
2684 int stdarg_p ATTRIBUTE_UNUSED;
2686 rtx nextarg ATTRIBUTE_UNUSED;
2688 tree field_reg, field_stk, field_arg;
2689 tree reg, stk, arg, t;
2691 field_arg = TYPE_FIELDS (va_list_type_node);
2692 field_stk = TREE_CHAIN (field_arg);
2693 field_reg = TREE_CHAIN (field_stk);
2695 arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
2696 stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
2697 reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
2699 /* Fill in the ARG member. */
2701 tree fntype = TREE_TYPE (current_function_decl);
2702 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2703 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2704 != void_type_node)))
2705 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
2708 if (CONSTANT_P (current_function_arg_offset_rtx))
2710 int fixed = (INTVAL (current_function_arg_offset_rtx)
2711 + argadj) / UNITS_PER_WORD;
2713 argsize = build_int_2 (fixed, 0);
2717 argsize = make_tree (integer_type_node,
2718 current_function_arg_offset_rtx);
2719 argsize = fold (build (PLUS_EXPR, integer_type_node, argsize,
2720 build_int_2 (argadj, 0)));
2721 argsize = fold (build (RSHIFT_EXPR, integer_type_node, argsize,
2722 build_int_2 (2, 0)));
2725 t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, argsize);
2726 TREE_SIDE_EFFECTS (t) = 1;
2727 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2730 /* Store the arg pointer in the __va_stk member. */
2731 t = make_tree (TREE_TYPE (stk), virtual_incoming_args_rtx);
2732 t = build (MODIFY_EXPR, TREE_TYPE (stk), stk, t);
2733 TREE_SIDE_EFFECTS (t) = 1;
2734 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2736 /* Tuck the return value from __builtin_saveregs into __va_reg. */
2737 t = make_tree (TREE_TYPE (reg), expand_builtin_saveregs ());
2738 t = build (MODIFY_EXPR, TREE_TYPE (reg), reg, t);
2739 TREE_SIDE_EFFECTS (t) = 1;
2740 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2743 /* Implement `va_arg'. */
2746 m88k_va_arg (valist, type)
2749 tree field_reg, field_stk, field_arg;
2750 tree reg, stk, arg, arg_align, base, t;
2751 int size, wsize, align, reg_p;
2754 field_arg = TYPE_FIELDS (va_list_type_node);
2755 field_stk = TREE_CHAIN (field_arg);
2756 field_reg = TREE_CHAIN (field_stk);
2758 arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
2759 stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
2760 reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
2762 size = int_size_in_bytes (type);
2763 wsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
2764 align = 1 << ((TYPE_ALIGN (type) / BITS_PER_UNIT) >> 3);
2765 reg_p = (AGGREGATE_TYPE_P (type)
2766 ? size == UNITS_PER_WORD && TYPE_ALIGN (type) == BITS_PER_WORD
2767 : size <= 2*UNITS_PER_WORD);
2769 /* Align __va_arg to the (doubleword?) boundary above. */
2770 t = build (PLUS_EXPR, TREE_TYPE (arg), arg, build_int_2 (align - 1, 0));
2771 arg_align = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
2772 arg_align = save_expr (arg_align);
2774 /* Decide if we should read from stack or regs. */
2775 t = build (LT_EXPR, integer_type_node, arg_align, build_int_2 (8, 0));
2776 base = build (COND_EXPR, TREE_TYPE (reg), t, reg, stk);
2778 /* Find the final address. */
2779 t = build (PLUS_EXPR, TREE_TYPE (base), base, arg_align);
2780 addr_rtx = expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
2781 addr_rtx = copy_to_reg (addr_rtx);
2783 /* Increment __va_arg. */
2784 t = build (PLUS_EXPR, TREE_TYPE (arg), arg_align, build_int_2 (wsize, 0));
2785 t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, t);
2786 TREE_SIDE_EFFECTS (t) = 1;
2787 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2792 /* If cmpsi has not been generated, emit code to do the test. Return the
2793 expression describing the test of operator OP. */
2796 emit_test (op, mode)
2798 enum machine_mode mode;
2800 if (m88k_compare_reg == 0)
2801 emit_insn (gen_test (m88k_compare_op0, m88k_compare_op1));
2802 return (gen_rtx (op, mode, m88k_compare_reg, const0_rtx));
2805 /* Determine how to best perform cmpsi/bxx, where cmpsi has a constant
2806 operand. All tests with zero (albeit swapped) and all equality tests
2807 with a constant are done with bcnd. The remaining cases are swapped
2811 emit_bcnd (op, label)
2815 if (m88k_compare_op1 == const0_rtx)
2816 emit_jump_insn (gen_bcnd
2817 (gen_rtx (op, VOIDmode,m88k_compare_op0, const0_rtx),
2819 else if (m88k_compare_op0 == const0_rtx)
2820 emit_jump_insn (gen_bcnd
2821 (gen_rtx (swap_condition (op),
2822 VOIDmode, m88k_compare_op1, const0_rtx),
2824 else if (op != EQ && op != NE)
2825 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2828 rtx zero = gen_reg_rtx (SImode);
2832 if (GET_CODE (m88k_compare_op1) == CONST_INT)
2834 reg = force_reg (SImode, m88k_compare_op0);
2835 constant = m88k_compare_op1;
2839 reg = force_reg (SImode, m88k_compare_op1);
2840 constant = m88k_compare_op0;
2842 value = INTVAL (constant);
2844 /* Perform an arithmetic computation to make the compared-to value
2845 zero, but avoid loosing if the bcnd is later changed into sxx. */
2846 if (SMALL_INTVAL (value))
2847 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2850 if (SMALL_INTVAL (-value))
2851 emit_insn (gen_addsi3 (zero, reg,
2854 emit_insn (gen_xorsi3 (zero, reg, constant));
2856 emit_jump_insn (gen_bcnd (gen_rtx (op, VOIDmode,
2863 /* Print an operand. Recognize special options, documented below. */
2866 print_operand (file, x, code)
2871 enum rtx_code xc = (x ? GET_CODE (x) : UNKNOWN);
2872 register int value = (xc == CONST_INT ? INTVAL (x) : 0);
2873 static int sequencep;
2874 static int reversep;
2878 if (code < 'B' || code > 'E')
2879 output_operand_lossage ("%%R not followed by %%B/C/D/E");
2881 xc = reverse_condition (xc);
2887 case '*': /* addressing base register for PIC */
2888 fputs (reg_names[PIC_OFFSET_TABLE_REGNUM], file); return;
2890 case '#': /* SVR4 pound-sign syntax character (empty if SVR3) */
2891 fputs (m88k_pound_sign, file); return;
2893 case 'V': /* Output a serializing instruction as needed if the operand
2894 (assumed to be a MEM) is a volatile load. */
2895 case 'v': /* ditto for a volatile store. */
2896 if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE)
2898 /* The m88110 implements two FIFO queues, one for loads and
2899 one for stores. These queues mean that loads complete in
2900 their issue order as do stores. An interaction between the
2901 history buffer and the store reservation station ensures
2902 that a store will not bypass load. Finally, a load will not
2903 bypass store, but only when they reference the same address.
2905 To avoid this reordering (a load bypassing a store) for
2906 volatile references, a serializing instruction is output.
2907 We choose the fldcr instruction as it does not serialize on
2908 the m88100 so that -m88000 code will not be degraded.
2910 The mechanism below is completed by having CC_STATUS_INIT set
2911 the code to the unknown value. */
2915 A problem with 88110 4.1 & 4.2 makes the use of fldcr for
2916 this purpose undesirable. Instead we will use tb1, this will
2917 cause serialization on the 88100 but such is life.
2920 static rtx last_addr = 0;
2921 if (code == 'V' /* Only need to serialize before a load. */
2922 && m88k_volatile_code != 'V' /* Loads complete in FIFO order. */
2923 && !(m88k_volatile_code == 'v'
2924 && GET_CODE (XEXP (x, 0)) == LO_SUM
2925 && rtx_equal_p (XEXP (XEXP (x, 0), 1), last_addr)))
2929 "fldcr\t %s,%scr63\n\t",
2931 "fldcr\t %s,%sfcr63\n\t",
2933 reg_names[0], m88k_pound_sign);
2935 "tb1\t 1,%s,0xff\n\t", reg_names[0]);
2937 m88k_volatile_code = code;
2938 last_addr = (GET_CODE (XEXP (x, 0)) == LO_SUM
2939 ? XEXP (XEXP (x, 0), 1) : 0);
2943 case 'X': /* print the upper 16 bits... */
2945 case 'x': /* print the lower 16 bits of the integer constant in hex */
2946 if (xc != CONST_INT)
2947 output_operand_lossage ("invalid %%x/X value");
2948 fprintf (file, "0x%x", value & 0xffff); return;
2950 case 'H': /* print the low 16 bits of the negated integer constant */
2951 if (xc != CONST_INT)
2952 output_operand_lossage ("invalid %%H value");
2954 case 'h': /* print the register or low 16 bits of the integer constant */
2957 if (xc != CONST_INT)
2958 output_operand_lossage ("invalid %%h value");
2959 fprintf (file, "%d", value & 0xffff);
2962 case 'Q': /* print the low 8 bits of the negated integer constant */
2963 if (xc != CONST_INT)
2964 output_operand_lossage ("invalid %%Q value");
2966 case 'q': /* print the register or low 8 bits of the integer constant */
2969 if (xc != CONST_INT)
2970 output_operand_lossage ("invalid %%q value");
2971 fprintf (file, "%d", value & 0xff);
2974 case 'w': /* print the integer constant (X == 32 ? 0 : 32 - X) */
2975 if (xc != CONST_INT)
2976 output_operand_lossage ("invalid %%o value");
2977 fprintf (file, "%d", value == 32 ? 0 : 32 - value);
2980 case 'p': /* print the logarithm of the integer constant */
2982 || (value = exact_log2 (value)) < 0)
2983 output_operand_lossage ("invalid %%p value");
2984 fprintf (file, "%d", value);
2987 case 'S': /* compliment the value and then... */
2989 case 's': /* print the width and offset values forming the integer
2990 constant with a SET instruction. See integer_ok_for_set. */
2992 register unsigned mask, uval = value;
2993 register int top, bottom;
2995 if (xc != CONST_INT)
2996 output_operand_lossage ("invalid %%s/S value");
2997 /* All the "one" bits must be contiguous. If so, MASK will be
2998 a power of two or zero. */
2999 mask = (uval | (uval - 1)) + 1;
3000 if (!(uval && POWER_OF_2_or_0 (mask)))
3001 output_operand_lossage ("invalid %%s/S value");
3002 top = mask ? exact_log2 (mask) : 32;
3003 bottom = exact_log2 (uval & ~(uval - 1));
3004 fprintf (file,"%d<%d>", top - bottom, bottom);
3008 case 'P': /* print nothing if pc_rtx; output label_ref */
3009 if (xc == LABEL_REF)
3010 output_addr_const (file, x);
3012 output_operand_lossage ("invalid %%P operand");
3015 case 'L': /* print 0 or 1 if operand is label_ref and then... */
3016 fputc (xc == LABEL_REF ? '1' : '0', file);
3017 case '.': /* print .n if delay slot is used */
3018 fputs ((final_sequence
3019 && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
3020 ? ".n\t" : "\t", file);
3023 case '!': /* Reverse the following condition. */
3027 case 'R': /* reverse the condition of the next print_operand
3028 if operand is a label_ref. */
3030 reversep = (xc == LABEL_REF);
3033 case 'B': /* bcnd branch values */
3034 fputs (m88k_pound_sign, file);
3037 case EQ: fputs ("eq0", file); return;
3038 case NE: fputs ("ne0", file); return;
3039 case GT: fputs ("gt0", file); return;
3040 case LE: fputs ("le0", file); return;
3041 case LT: fputs ("lt0", file); return;
3042 case GE: fputs ("ge0", file); return;
3043 default: output_operand_lossage ("invalid %%B value");
3046 case 'C': /* bb0/bb1 branch values for comparisons */
3047 fputs (m88k_pound_sign, file);
3050 case EQ: fputs ("eq", file); return;
3051 case NE: fputs ("ne", file); return;
3052 case GT: fputs ("gt", file); return;
3053 case LE: fputs ("le", file); return;
3054 case LT: fputs ("lt", file); return;
3055 case GE: fputs ("ge", file); return;
3056 case GTU: fputs ("hi", file); return;
3057 case LEU: fputs ("ls", file); return;
3058 case LTU: fputs ("lo", file); return;
3059 case GEU: fputs ("hs", file); return;
3060 default: output_operand_lossage ("invalid %%C value");
3063 case 'D': /* bcnd branch values for float comparisons */
3066 case EQ: fputs ("0xa", file); return;
3067 case NE: fputs ("0x5", file); return;
3068 case GT: fputs (m88k_pound_sign, file);
3069 fputs ("gt0", file); return;
3070 case LE: fputs ("0xe", file); return;
3071 case LT: fputs ("0x4", file); return;
3072 case GE: fputs ("0xb", file); return;
3073 default: output_operand_lossage ("invalid %%D value");
3076 case 'E': /* bcnd branch values for special integers */
3079 case EQ: fputs ("0x8", file); return;
3080 case NE: fputs ("0x7", file); return;
3081 default: output_operand_lossage ("invalid %%E value");
3084 case 'd': /* second register of a two register pair */
3086 output_operand_lossage ("`%%d' operand isn't a register");
3087 fputs (reg_names[REGNO (x) + 1], file);
3090 case 'r': /* an immediate 0 should be represented as `r0' */
3091 if (x == const0_rtx)
3093 fputs (reg_names[0], file);
3097 output_operand_lossage ("invalid %%r value");
3103 if (REGNO (x) == ARG_POINTER_REGNUM)
3104 output_operand_lossage ("operand is r0");
3106 fputs (reg_names[REGNO (x)], file);
3108 else if (xc == PLUS)
3111 output_address (XEXP (x, 0));
3112 else if (flag_pic && xc == UNSPEC)
3114 output_addr_const (file, XVECEXP (x, 0, 0));
3115 fputs ("#got_rel", file);
3117 else if (xc == CONST_DOUBLE)
3118 output_operand_lossage ("operand is const_double");
3120 output_addr_const (file, x);
3123 case 'g': /* append #got_rel as needed */
3124 if (flag_pic && (xc == SYMBOL_REF || xc == LABEL_REF))
3126 output_addr_const (file, x);
3127 fputs ("#got_rel", file);
3132 case 'a': /* (standard), assume operand is an address */
3133 case 'c': /* (standard), assume operand is an immediate value */
3134 case 'l': /* (standard), assume operand is a label_ref */
3135 case 'n': /* (standard), like %c, except negate first */
3137 output_operand_lossage ("invalid code");
3142 print_operand_address (file, addr)
3146 register rtx reg0, reg1, temp;
3148 switch (GET_CODE (addr))
3151 if (REGNO (addr) == ARG_POINTER_REGNUM)
3154 fprintf (file, "%s,%s", reg_names[0], reg_names [REGNO (addr)]);
3158 fprintf (file, "%s,%slo16(",
3159 reg_names[REGNO (XEXP (addr, 0))], m88k_pound_sign);
3160 output_addr_const (file, XEXP (addr, 1));
3165 reg0 = XEXP (addr, 0);
3166 reg1 = XEXP (addr, 1);
3167 if (GET_CODE (reg0) == MULT || GET_CODE (reg0) == CONST_INT)
3174 if ((REG_P (reg0) && REGNO (reg0) == ARG_POINTER_REGNUM)
3175 || (REG_P (reg1) && REGNO (reg1) == ARG_POINTER_REGNUM))
3178 else if (REG_P (reg0))
3181 fprintf (file, "%s,%s",
3182 reg_names [REGNO (reg0)], reg_names [REGNO (reg1)]);
3184 else if (GET_CODE (reg1) == CONST_INT)
3185 fprintf (file, "%s,%d",
3186 reg_names [REGNO (reg0)], INTVAL (reg1));
3188 else if (GET_CODE (reg1) == MULT)
3190 rtx mreg = XEXP (reg1, 0);
3191 if (REGNO (mreg) == ARG_POINTER_REGNUM)
3194 fprintf (file, "%s[%s]", reg_names[REGNO (reg0)],
3195 reg_names[REGNO (mreg)]);
3198 else if (GET_CODE (reg1) == ZERO_EXTRACT)
3200 fprintf (file, "%s,%slo16(",
3201 reg_names[REGNO (reg0)], m88k_pound_sign);
3202 output_addr_const (file, XEXP (reg1, 0));
3208 fprintf (file, "%s,", reg_names[REGNO (reg0)]);
3209 output_addr_const (file, reg1);
3210 fputs ("#got_rel", file);
3220 if (REGNO (XEXP (addr, 0)) == ARG_POINTER_REGNUM)
3223 fprintf (file, "%s[%s]",
3224 reg_names[0], reg_names[REGNO (XEXP (addr, 0))]);
3228 fprintf (file, "%s,%d", reg_names[0], INTVAL (addr));
3232 fprintf (file, "%s,", reg_names[0]);
3233 if (SHORT_ADDRESS_P (addr, temp))
3235 fprintf (file, "%siw16(", m88k_pound_sign);
3236 output_addr_const (file, addr);
3240 output_addr_const (file, addr);
3244 /* Return true if X is an address which needs a temporary register when
3245 reloaded while generating PIC code. */
3248 pic_address_needs_scratch (x)
3251 /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */
3252 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
3253 && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
3254 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
3255 && ! ADD_INT (XEXP (XEXP (x, 0), 1)))
3261 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
3262 reference and a constant. */
3265 symbolic_operand (op, mode)
3267 enum machine_mode mode;
3269 switch (GET_CODE (op))
3277 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
3278 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
3279 && GET_CODE (XEXP (op, 1)) == CONST_INT);
3281 /* ??? This clause seems to be irrelevant. */
3283 return GET_MODE (op) == mode;
3290 #if defined (CTOR_LIST_BEGIN) && !defined (OBJECT_FORMAT_ELF)
3292 m88k_svr3_asm_out_constructor (symbol, priority)
3294 int priority ATTRIBUTE_UNUSED;
3296 const char *name = XSTR (symbol, 0);
3299 fprintf (asm_out_file, "\tor.u\t r13,r0,hi16(");
3300 assemble_name (asm_out_file, name);
3301 fprintf (asm_out_file, ")\n\tor\t r13,r13,lo16(");
3302 assemble_name (asm_out_file, name);
3303 fprintf (asm_out_file, ")\n\tsubu\t r31,r31,%d\n\tst\t r13,r31,%d\n",
3304 STACK_BOUNDARY / BITS_PER_UNIT, REG_PARM_STACK_SPACE (0));
3308 m88k_svr3_asm_out_destructor (symbol, priority)
3310 int priority ATTRIBUTE_UNUSED;
3315 assemble_integer (symbol, UNITS_PER_WORD, BITS_PER_WORD, 1);
3316 for (i = 1; i < 4; i++)
3317 assemble_integer (constm1_rtx, UNITS_PER_WORD, BITS_PER_WORD, 1);
3319 #endif /* INIT_SECTION_ASM_OP && ! OBJECT_FORMAT_ELF */
3321 /* Adjust the cost of INSN based on the relationship between INSN that
3322 is dependent on DEP_INSN through the dependence LINK. The default
3323 is to make no adjustment to COST.
3325 On the m88k, ignore the cost of anti- and output-dependencies. On
3326 the m88100, a store can issue two cycles before the value (not the
3327 address) has finished computing. */
3330 m88k_adjust_cost (insn, link, dep, cost)
3336 if (REG_NOTE_KIND (link) != 0)
3337 return 0; /* Anti or output dependence. */
3340 && recog_memoized (insn) >= 0
3341 && get_attr_type (insn) == TYPE_STORE
3342 && SET_SRC (PATTERN (insn)) == SET_DEST (PATTERN (dep)))
3343 return cost - 4; /* 88110 store reservation station. */