1 /* Subroutines for insn-output.c for Motorola 88000.
2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002 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));
74 static void m88k_select_section PARAMS ((tree, int, unsigned HOST_WIDE_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;
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 REAL_VALUE_FROM_CONST_DOUBLE (d, op);
1151 REAL_VALUE_TO_TARGET_DOUBLE (d, u.l);
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;
1175 struct { /* IEEE double precision format */
1177 unsigned exponent : 11;
1178 unsigned mantissa1 : 20;
1181 struct { /* IEEE double format to quick check */
1182 unsigned sign : 1; /* if it fits in a float */
1183 unsigned exponent1 : 4;
1184 unsigned exponent2 : 7;
1185 unsigned mantissa1 : 20;
1190 if (GET_CODE (op) == REG || mode != DFmode)
1193 if (GET_CODE (op) == CONST_DOUBLE)
1195 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
1196 REAL_VALUE_TO_TARGET_DOUBLE (r, u.l);
1197 if (u.d.exponent != 0x7ff /* NaN */
1198 && u.d.mantissa2 == 0 /* Mantissa fits */
1199 && (u.s.exponent1 == 0x8 || u.s.exponent1 == 0x7) /* Exponent fits */
1200 && (temp = simplify_unary_operation (FLOAT_TRUNCATE, SFmode,
1202 return gen_rtx_FLOAT_EXTEND (mode, force_reg (SFmode, temp));
1204 else if (register_operand (op, mode))
1207 return force_reg (mode, op);
1210 /* Return true if OP is a suitable input for a move insn. */
1213 move_operand (op, mode)
1215 enum machine_mode mode;
1217 if (register_operand (op, mode))
1219 if (GET_CODE (op) == CONST_INT)
1220 return (classify_integer (mode, INTVAL (op)) < m88k_oru_hi16);
1221 if (GET_MODE (op) != mode)
1223 if (GET_CODE (op) == SUBREG)
1224 op = SUBREG_REG (op);
1225 if (GET_CODE (op) != MEM)
1229 if (GET_CODE (op) == LO_SUM)
1230 return (REG_P (XEXP (op, 0))
1231 && symbolic_address_p (XEXP (op, 1)));
1232 return memory_address_p (mode, op);
1235 /* Return true if OP is suitable for a call insn. */
1238 call_address_operand (op, mode)
1240 enum machine_mode mode ATTRIBUTE_UNUSED;
1242 return (REG_P (op) || symbolic_address_p (op));
1245 /* Returns true if OP is either a symbol reference or a sum of a symbol
1246 reference and a constant. */
1249 symbolic_address_p (op)
1252 switch (GET_CODE (op))
1260 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1261 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1262 && GET_CODE (XEXP (op, 1)) == CONST_INT);
1269 /* Return true if OP is a register or const0_rtx. */
1272 reg_or_0_operand (op, mode)
1274 enum machine_mode mode;
1276 return (op == const0_rtx || register_operand (op, mode));
1279 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
1282 arith_operand (op, mode)
1284 enum machine_mode mode;
1286 return (register_operand (op, mode)
1287 || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
1290 /* Return true if OP is a register or 5 bit integer. */
1293 arith5_operand (op, mode)
1295 enum machine_mode mode;
1297 return (register_operand (op, mode)
1298 || (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32));
1302 arith32_operand (op, mode)
1304 enum machine_mode mode;
1306 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
1310 arith64_operand (op, mode)
1312 enum machine_mode mode;
1314 return (register_operand (op, mode)
1315 || GET_CODE (op) == CONST_INT
1316 || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode));
1320 int5_operand (op, mode)
1322 enum machine_mode mode ATTRIBUTE_UNUSED;
1324 return (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32);
1328 int32_operand (op, mode)
1330 enum machine_mode mode ATTRIBUTE_UNUSED;
1332 return (GET_CODE (op) == CONST_INT);
1335 /* Return true if OP is a register or a valid immediate operand for
1339 add_operand (op, mode)
1341 enum machine_mode mode;
1343 return (register_operand (op, mode)
1344 || (GET_CODE (op) == CONST_INT && ADD_INT (op)));
1347 /* Nonzero if this is a bitmask filling the bottom bits, for optimizing and +
1348 shift left combinations into a single mak instruction. */
1354 return (value && POWER_OF_2_or_0 (value + 1));
1358 reg_or_bbx_mask_operand (op, mode)
1360 enum machine_mode mode;
1363 if (register_operand (op, mode))
1365 if (GET_CODE (op) != CONST_INT)
1368 value = INTVAL (op);
1369 if (POWER_OF_2 (value))
1375 /* Return true if OP is valid to use in the context of a floating
1376 point operation. Special case 0.0, since we can use r0. */
1379 real_or_0_operand (op, mode)
1381 enum machine_mode mode;
1383 if (mode != SFmode && mode != DFmode)
1386 return (register_operand (op, mode)
1387 || (GET_CODE (op) == CONST_DOUBLE
1388 && op == CONST0_RTX (mode)));
1391 /* Return true if OP is valid to use in the context of logic arithmetic
1392 on condition codes. */
1395 partial_ccmode_register_operand (op, mode)
1397 enum machine_mode mode ATTRIBUTE_UNUSED;
1399 return register_operand (op, CCmode) || register_operand (op, CCEVENmode);
1402 /* Return true if OP is a relational operator. */
1407 enum machine_mode mode ATTRIBUTE_UNUSED;
1409 switch (GET_CODE (op))
1428 even_relop (op, mode)
1430 enum machine_mode mode ATTRIBUTE_UNUSED;
1432 switch (GET_CODE (op))
1446 odd_relop (op, mode)
1448 enum machine_mode mode ATTRIBUTE_UNUSED;
1450 switch (GET_CODE (op))
1463 /* Return true if OP is a relational operator, and is not an unsigned
1464 relational operator. */
1467 relop_no_unsigned (op, mode)
1469 enum machine_mode mode ATTRIBUTE_UNUSED;
1471 switch (GET_CODE (op))
1479 /* @@ What is this test doing? Why not use `mode'? */
1480 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
1481 || GET_MODE (op) == DImode
1482 || GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_FLOAT
1483 || GET_MODE (XEXP (op, 0)) == DImode
1484 || GET_MODE_CLASS (GET_MODE (XEXP (op, 1))) == MODE_FLOAT
1485 || GET_MODE (XEXP (op, 1)) == DImode)
1493 /* Return true if the code of this rtx pattern is EQ or NE. */
1496 equality_op (op, mode)
1498 enum machine_mode mode ATTRIBUTE_UNUSED;
1500 return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
1503 /* Return true if the code of this rtx pattern is pc or label_ref. */
1506 pc_or_label_ref (op, mode)
1508 enum machine_mode mode ATTRIBUTE_UNUSED;
1510 return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF);
1513 /* Output to FILE the start of the assembler file. */
1515 /* This definition must match lang_independent_options from toplev.c. */
1516 struct m88k_lang_independent_options
1518 const char *const string;
1519 int *const variable;
1521 const char *const description;
1524 static void output_options PARAMS ((FILE *,
1525 const struct m88k_lang_independent_options *,
1527 const struct m88k_lang_independent_options *,
1528 int, int, int, const char *, const char *,
1532 output_option (file, sep, type, name, indent, pos, max)
1541 if ((long)(strlen (sep) + strlen (type) + strlen (name) + pos) > max)
1543 fprintf (file, indent);
1544 return fprintf (file, "%s%s", type, name);
1546 return pos + fprintf (file, "%s%s%s", sep, type, name);
1549 static const struct { const char *const name; const int value; } m_options[] =
1553 output_options (file, f_options, f_len, W_options, W_len,
1554 pos, max, sep, indent, term)
1556 const struct m88k_lang_independent_options *f_options;
1557 const struct m88k_lang_independent_options *W_options;
1568 pos = output_option (file, sep, "-O", "", indent, pos, max);
1569 if (write_symbols != NO_DEBUG)
1570 pos = output_option (file, sep, "-g", "", indent, pos, max);
1572 pos = output_option (file, sep, "-p", "", indent, pos, max);
1573 for (j = 0; j < f_len; j++)
1574 if (*f_options[j].variable == f_options[j].on_value)
1575 pos = output_option (file, sep, "-f", f_options[j].string,
1578 for (j = 0; j < W_len; j++)
1579 if (*W_options[j].variable == W_options[j].on_value)
1580 pos = output_option (file, sep, "-W", W_options[j].string,
1583 for (j = 0; j < (long) ARRAY_SIZE (m_options); j++)
1584 if (m_options[j].name[0] != '\0'
1585 && m_options[j].value > 0
1586 && ((m_options[j].value & target_flags)
1587 == m_options[j].value))
1588 pos = output_option (file, sep, "-m", m_options[j].name,
1591 if (m88k_short_data)
1592 pos = output_option (file, sep, "-mshort-data-", m88k_short_data,
1595 fprintf (file, term);
1599 output_file_start (file, f_options, f_len, W_options, W_len)
1601 const struct m88k_lang_independent_options *f_options;
1602 const struct m88k_lang_independent_options *W_options;
1607 ASM_FIRST_LINE (file);
1610 fprintf (file, "%s\n", REQUIRES_88110_ASM_OP);
1611 output_file_directive (file, main_input_filename);
1612 /* Switch to the data section so that the coffsem symbol
1613 isn't in the text section. */
1616 if (TARGET_IDENTIFY_REVISION)
1620 time_t now = time ((time_t *)0);
1621 sprintf (indent, "]\"\n%s\"@(#)%s [", IDENT_ASM_OP, main_input_filename);
1622 fprintf (file, indent+3);
1623 pos = fprintf (file, "gcc %s, %.24s,", version_string, ctime (&now));
1625 /* ??? It would be nice to call print_switch_values here (and thereby
1626 let us delete output_options) but this is kept in until it is known
1627 whether the change in content format matters. */
1628 output_options (file, f_options, f_len, W_options, W_len,
1629 pos, 150 - strlen (indent), " ", indent, "]\"\n\n");
1631 fprintf (file, "]\"\n");
1632 print_switch_values (file, 0, 150 - strlen (indent),
1633 indent + 3, " ", "]\"\n");
1638 /* Output an ascii string. */
1641 output_ascii (file, opcode, max, p, size)
1651 register int num = 0;
1653 fprintf (file, "%s\"", opcode);
1654 for (i = 0; i < size; i++)
1656 register int c = (unsigned char) p[i];
1660 fprintf (file, "\"\n%s\"", opcode);
1664 if (c == '\"' || c == '\\')
1672 else if (in_escape && ISDIGIT (c))
1674 /* If a digit follows an octal-escape, the VAX assembler fails
1675 to stop reading the escape after three digits. Continue to
1676 output the values as an octal-escape until a non-digit is
1678 fprintf (file, "\\%03o", c);
1681 else if ((c >= ' ' && c < 0177) || (c == '\t'))
1691 /* Some assemblers can't handle \a, \v, or \?. */
1692 case '\f': c = 'f'; goto escape;
1693 case '\b': c = 'b'; goto escape;
1694 case '\r': c = 'r'; goto escape;
1695 case '\n': c = 'n'; goto escape;
1698 fprintf (file, "\\%03o", c);
1703 fprintf (file, "\"\n");
1706 /* Output a label (allows insn-output.c to be compiled without including
1707 m88k.c or needing to include stdio.h). */
1710 output_label (label_number)
1713 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", label_number);
1716 /* Generate the assembly code for function entry.
1718 The prologue is responsible for setting up the stack frame,
1719 initializing the frame pointer register, saving registers that must be
1720 saved, and allocating SIZE additional bytes of storage for the
1721 local variables. SIZE is an integer. FILE is a stdio
1722 stream to which the assembler code should be output.
1724 The label for the beginning of the function need not be output by this
1725 macro. That has already been done when the macro is run.
1727 To determine which registers to save, the macro can refer to the array
1728 `regs_ever_live': element R is nonzero if hard register
1729 R is used anywhere within the function. This implies the
1730 function prologue should save register R, but not if it is one
1731 of the call-used registers.
1733 On machines where functions may or may not have frame-pointers, the
1734 function entry code must vary accordingly; it must set up the frame
1735 pointer if one is wanted, and not otherwise. To determine whether a
1736 frame pointer is in wanted, the macro can refer to the variable
1737 `frame_pointer_needed'. The variable's value will be 1 at run
1738 time in a function that needs a frame pointer.
1740 On machines where an argument may be passed partly in registers and
1741 partly in memory, this macro must examine the variable
1742 `current_function_pretend_args_size', and allocate that many bytes
1743 of uninitialized space on the stack just underneath the first argument
1744 arriving on the stack. (This may not be at the very end of the stack,
1745 if the calling sequence has pushed anything else since pushing the stack
1746 arguments. But usually, on such machines, nothing else has been pushed
1747 yet, because the function prologue itself does all the pushing.)
1749 If `ACCUMULATE_OUTGOING_ARGS' is defined, the variable
1750 `current_function_outgoing_args_size' contains the size in bytes
1751 required for the outgoing arguments. This macro must add that
1752 amount of uninitialized space to very bottom of the stack.
1754 The stack frame we use looks like this:
1757 |==============================================|
1759 |==============================================|
1760 | [caller's outgoing memory arguments] |
1761 |==============================================|
1762 | caller's outgoing argument area (32 bytes) |
1763 sp -> |==============================================| <- ap
1764 | [local variable space] |
1765 |----------------------------------------------|
1766 | [return address (r1)] |
1767 |----------------------------------------------|
1768 | [previous frame pointer (r30)] |
1769 |==============================================| <- fp
1770 | [preserved registers (r25..r14)] |
1771 |----------------------------------------------|
1772 | [preserved registers (x29..x22)] |
1773 |==============================================|
1774 | [dynamically allocated space (alloca)] |
1775 |==============================================|
1776 | [callee's outgoing memory arguments] |
1777 |==============================================|
1778 | [callee's outgoing argument area (32 bytes)] |
1779 |==============================================| <- sp
1783 r1 and r30 must be saved if debugging.
1785 fp (if present) is located two words down from the local
1789 static void emit_add PARAMS ((rtx, rtx, int));
1790 static void preserve_registers PARAMS ((int, int));
1791 static void emit_ldst PARAMS ((int, int, enum machine_mode, int));
1792 static void output_tdesc PARAMS ((FILE *, int));
1793 static int uses_arg_area_p PARAMS ((void));
1797 static char save_regs[FIRST_PSEUDO_REGISTER];
1798 static int frame_laid_out;
1799 static int frame_size;
1800 static int variable_args_p;
1801 static int epilogue_marked;
1802 static int prologue_marked;
1804 #define FIRST_OCS_PRESERVE_REGISTER 14
1805 #define LAST_OCS_PRESERVE_REGISTER 30
1807 #define FIRST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 22)
1808 #define LAST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 31)
1810 #define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
1811 #define ROUND_CALL_BLOCK_SIZE(BYTES) \
1812 (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
1814 /* Establish the position of the FP relative to the SP. This is done
1815 either during output_function_prologue() or by
1816 INITIAL_ELIMINATION_OFFSET. */
1819 m88k_layout_frame ()
1825 memset ((char *) &save_regs[0], 0, sizeof (save_regs));
1826 sp_size = nregs = nxregs = 0;
1827 frame_size = get_frame_size ();
1829 /* Since profiling requires a call, make sure r1 is saved. */
1830 if (current_function_profile)
1833 /* If we are producing debug information, store r1 and r30 where the
1834 debugger wants to find them (r30 at r30+0, r1 at r30+4). Space has
1835 already been reserved for r1/r30 in STARTING_FRAME_OFFSET. */
1836 if (write_symbols != NO_DEBUG && !TARGET_OCS_FRAME_POSITION)
1839 /* If there is a call, alloca is used, __builtin_alloca is used, or
1840 a dynamic-sized object is defined, add the 8 additional words
1841 for the callee's argument area. The common denominator is that the
1842 FP is required. may_call_alloca only gets calls to alloca;
1843 current_function_calls_alloca gets alloca and __builtin_alloca. */
1844 if (regs_ever_live[1] || frame_pointer_needed)
1847 sp_size += REG_PARM_STACK_SPACE (0);
1850 /* If we are producing PIC, save the addressing base register and r1. */
1851 if (flag_pic && current_function_uses_pic_offset_table)
1853 save_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
1857 /* If a frame is requested, save the previous FP, and the return
1858 address (r1), so that a traceback can be done without using tdesc
1859 information. Otherwise, simply save the FP if it is used as
1860 a preserve register. */
1861 if (frame_pointer_needed)
1862 save_regs[FRAME_POINTER_REGNUM] = save_regs[1] = 1;
1863 else if (regs_ever_live[FRAME_POINTER_REGNUM])
1864 save_regs[FRAME_POINTER_REGNUM] = 1;
1866 /* Figure out which extended register(s) needs to be saved. */
1867 for (regno = FIRST_EXTENDED_REGISTER + 1; regno < FIRST_PSEUDO_REGISTER;
1869 if (regs_ever_live[regno] && ! call_used_regs[regno])
1871 save_regs[regno] = 1;
1875 /* Figure out which normal register(s) needs to be saved. */
1876 for (regno = 2; regno < FRAME_POINTER_REGNUM; regno++)
1877 if (regs_ever_live[regno] && ! call_used_regs[regno])
1879 save_regs[regno] = 1;
1883 /* Achieve greatest use of double memory ops. Either we end up saving
1884 r30 or we use that slot to align the registers we do save. */
1885 if (nregs >= 2 && save_regs[1] && !save_regs[FRAME_POINTER_REGNUM])
1888 nregs += save_regs[1] + save_regs[FRAME_POINTER_REGNUM];
1889 /* if we need to align extended registers, add a word */
1890 if (nxregs > 0 && (nregs & 1) != 0)
1892 sp_size += 4 * nregs;
1893 sp_size += 8 * nxregs;
1894 sp_size += current_function_outgoing_args_size;
1896 /* The first two saved registers are placed above the new frame pointer
1897 if any. In the only case this matters, they are r1 and r30. */
1898 if (frame_pointer_needed || sp_size)
1899 m88k_fp_offset = ROUND_CALL_BLOCK_SIZE (sp_size - STARTING_FRAME_OFFSET);
1901 m88k_fp_offset = -STARTING_FRAME_OFFSET;
1902 m88k_stack_size = m88k_fp_offset + STARTING_FRAME_OFFSET;
1904 /* First, combine m88k_stack_size and size. If m88k_stack_size is
1905 non-zero, align the frame size to 8 mod 16; otherwise align the
1906 frame size to 0 mod 16. (If stacks are 8 byte aligned, this ends
1910 = ((m88k_stack_size ? STACK_UNIT_BOUNDARY - STARTING_FRAME_OFFSET : 0)
1911 - (frame_size % STACK_UNIT_BOUNDARY));
1913 need += STACK_UNIT_BOUNDARY;
1915 = ROUND_CALL_BLOCK_SIZE (m88k_stack_size + frame_size + need
1916 + current_function_pretend_args_size);
1920 /* Return true if this function is known to have a null prologue. */
1925 if (! reload_completed)
1927 if (! frame_laid_out)
1928 m88k_layout_frame ();
1929 return (! frame_pointer_needed
1932 && m88k_stack_size == 0);
1935 /* Determine if the current function has any references to the arg pointer.
1936 This is done indirectly by examining the DECL_ARGUMENTS' DECL_RTL.
1937 It is OK to return TRUE if there are no references, but FALSE must be
1945 if (current_function_decl == 0
1946 || current_function_varargs
1950 for (parm = DECL_ARGUMENTS (current_function_decl);
1952 parm = TREE_CHAIN (parm))
1954 if (DECL_RTL (parm) == 0
1955 || GET_CODE (DECL_RTL (parm)) == MEM)
1958 if (DECL_INCOMING_RTL (parm) == 0
1959 || GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
1966 m88k_output_function_prologue (stream, size)
1967 FILE *stream ATTRIBUTE_UNUSED;
1968 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
1970 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! quiet_flag && leaf_function_p ())
1971 fprintf (stderr, "$");
1973 m88k_prologue_done = 1; /* it's ok now to put out ln directives */
1977 m88k_output_function_end_prologue (stream)
1980 if (TARGET_OCS_DEBUG_INFO && !prologue_marked)
1982 PUT_OCS_FUNCTION_START (stream);
1983 prologue_marked = 1;
1985 /* If we've already passed the start of the epilogue, say that
1986 it starts here. This marks the function as having a null body,
1987 but at a point where the return address is in a known location.
1989 Originally, I thought this couldn't happen, but the pic prologue
1990 for leaf functions ends with the instruction that restores the
1991 return address from the temporary register. If the temporary
1992 register is never used, that instruction can float all the way
1993 to the end of the function. */
1994 if (epilogue_marked)
1995 PUT_OCS_FUNCTION_END (stream);
2000 m88k_expand_prologue ()
2002 m88k_layout_frame ();
2004 if (TARGET_OPTIMIZE_ARG_AREA
2006 && ! uses_arg_area_p ())
2008 /* The incoming argument area is used for stack space if it is not
2009 used (or if -mno-optimize-arg-area is given). */
2010 if ((m88k_stack_size -= REG_PARM_STACK_SPACE (0)) < 0)
2011 m88k_stack_size = 0;
2014 if (m88k_stack_size)
2015 emit_add (stack_pointer_rtx, stack_pointer_rtx, -m88k_stack_size);
2017 if (nregs || nxregs)
2018 preserve_registers (m88k_fp_offset + 4, 1);
2020 if (frame_pointer_needed)
2021 emit_add (frame_pointer_rtx, stack_pointer_rtx, m88k_fp_offset);
2023 if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM])
2025 rtx return_reg = gen_rtx_REG (SImode, 1);
2026 rtx label = gen_label_rtx ();
2027 rtx temp_reg = NULL_RTX;
2031 temp_reg = gen_rtx_REG (SImode, TEMP_REGNUM);
2032 emit_move_insn (temp_reg, return_reg);
2034 emit_insn (gen_locate1 (pic_offset_table_rtx, label));
2035 emit_insn (gen_locate2 (pic_offset_table_rtx, label));
2036 emit_insn (gen_addsi3 (pic_offset_table_rtx,
2037 pic_offset_table_rtx, return_reg));
2039 emit_move_insn (return_reg, temp_reg);
2041 if (current_function_profile)
2042 emit_insn (gen_blockage ());
2045 /* This function generates the assembly code for function exit,
2046 on machines that need it.
2048 The function epilogue should not depend on the current stack pointer!
2049 It should use the frame pointer only, if there is a frame pointer.
2050 This is mandatory because of alloca; we also take advantage of it to
2051 omit stack adjustments before returning. */
2054 m88k_output_function_begin_epilogue (stream)
2057 if (TARGET_OCS_DEBUG_INFO && !epilogue_marked && prologue_marked)
2059 PUT_OCS_FUNCTION_END (stream);
2061 epilogue_marked = 1;
2065 m88k_output_function_epilogue (stream, size)
2067 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
2069 rtx insn = get_last_insn ();
2071 if (TARGET_OCS_DEBUG_INFO && !epilogue_marked)
2072 PUT_OCS_FUNCTION_END (stream);
2074 /* If the last insn isn't a BARRIER, we must write a return insn. This
2075 should only happen if the function has no prologue and no body. */
2076 if (GET_CODE (insn) == NOTE)
2077 insn = prev_nonnote_insn (insn);
2078 if (insn == 0 || GET_CODE (insn) != BARRIER)
2079 fprintf (stream, "\tjmp\t %s\n", reg_names[1]);
2081 /* If the last insn is a barrier, and the insn before that is a call,
2082 then add a nop instruction so that tdesc can walk the stack correctly
2083 even though there is no epilogue. (Otherwise, the label for the
2084 end of the tdesc region ends up at the start of the next function. */
2085 if (insn && GET_CODE (insn) == BARRIER)
2087 insn = prev_nonnote_insn (insn);
2088 if (insn && GET_CODE (insn) == CALL_INSN)
2089 fprintf (stream, "\tor\t %s,%s,%s\n",reg_names[0],reg_names[0],reg_names[0]);
2092 output_short_branch_defs (stream);
2094 fprintf (stream, "\n");
2096 if (TARGET_OCS_DEBUG_INFO)
2097 output_tdesc (stream, m88k_fp_offset + 4);
2099 m88k_function_number++;
2100 m88k_prologue_done = 0; /* don't put out ln directives */
2101 variable_args_p = 0; /* has variable args */
2103 epilogue_marked = 0;
2104 prologue_marked = 0;
2108 m88k_expand_epilogue ()
2110 #if (MONITOR_GCC & 0x4) /* What are interesting prologue/epilogue values? */
2111 fprintf (stream, "; size = %d, m88k_fp_offset = %d, m88k_stack_size = %d\n",
2112 size, m88k_fp_offset, m88k_stack_size);
2115 if (frame_pointer_needed)
2116 emit_add (stack_pointer_rtx, frame_pointer_rtx, -m88k_fp_offset);
2118 if (nregs || nxregs)
2119 preserve_registers (m88k_fp_offset + 4, 0);
2121 if (m88k_stack_size)
2122 emit_add (stack_pointer_rtx, stack_pointer_rtx, m88k_stack_size);
2125 /* Emit insns to set DSTREG to SRCREG + AMOUNT during the prologue or
2129 emit_add (dstreg, srcreg, amount)
2134 rtx incr = GEN_INT (abs (amount));
2136 if (! ADD_INTVAL (amount))
2138 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
2139 emit_move_insn (temp, incr);
2142 emit_insn ((amount < 0 ? gen_subsi3 : gen_addsi3) (dstreg, srcreg, incr));
2145 /* Save/restore the preserve registers. base is the highest offset from
2146 r31 at which a register is stored. store_p is true if stores are to
2147 be done; otherwise loads. */
2150 preserve_registers (base, store_p)
2159 } mem_op[FIRST_PSEUDO_REGISTER];
2160 struct mem_op *mo_ptr = mem_op;
2162 /* The 88open OCS mandates that preserved registers be stored in
2163 increasing order. For compatibility with current practice,
2164 the order is r1, r30, then the preserve registers. */
2169 /* An extra word is given in this case to make best use of double
2171 if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM])
2173 emit_ldst (store_p, 1, SImode, offset);
2178 /* Walk the registers to save recording all single memory operations. */
2179 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2180 if (save_regs[regno])
2182 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2185 mo_ptr->regno = regno;
2186 mo_ptr->offset = offset;
2197 /* Walk the registers to save recording all double memory operations.
2198 This avoids a delay in the epilogue (ld.d/ld). */
2200 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2201 if (save_regs[regno])
2203 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2210 mo_ptr->regno = regno-1;
2211 mo_ptr->offset = offset-4;
2218 /* Walk the extended registers to record all memory operations. */
2219 /* Be sure the offset is double word aligned. */
2220 offset = (offset - 1) & ~7;
2221 for (regno = FIRST_PSEUDO_REGISTER - 1; regno > FIRST_EXTENDED_REGISTER;
2223 if (save_regs[regno])
2226 mo_ptr->regno = regno;
2227 mo_ptr->offset = offset;
2234 /* Output the memory operations. */
2235 for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++)
2238 emit_ldst (store_p, mo_ptr->regno,
2239 (mo_ptr->nregs > 1 ? DImode : SImode),
2245 emit_ldst (store_p, regno, mode, offset)
2248 enum machine_mode mode;
2251 rtx reg = gen_rtx_REG (mode, regno);
2254 if (SMALL_INTVAL (offset))
2256 mem = gen_rtx_MEM (mode, plus_constant (stack_pointer_rtx, offset));
2260 /* offset is too large for immediate index must use register */
2262 rtx disp = GEN_INT (offset);
2263 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
2264 rtx regi = gen_rtx_PLUS (SImode, stack_pointer_rtx, temp);
2266 emit_move_insn (temp, disp);
2267 mem = gen_rtx_MEM (mode, regi);
2271 emit_move_insn (mem, reg);
2273 emit_move_insn (reg, mem);
2276 /* Convert the address expression REG to a CFA offset. */
2279 m88k_debugger_offset (reg, offset)
2281 register int offset;
2283 if (GET_CODE (reg) == PLUS)
2285 offset = INTVAL (XEXP (reg, 1));
2286 reg = XEXP (reg, 0);
2289 /* Put the offset in terms of the CFA (arg pointer). */
2290 if (reg == frame_pointer_rtx)
2291 offset += m88k_fp_offset - m88k_stack_size;
2292 else if (reg == stack_pointer_rtx)
2293 offset -= m88k_stack_size;
2294 else if (reg != arg_pointer_rtx)
2296 #if (MONITOR_GCC & 0x10) /* Watch for suspicious symbolic locations. */
2297 if (! (GET_CODE (reg) == REG
2298 && REGNO (reg) >= FIRST_PSEUDO_REGISTER))
2299 warning ("internal gcc error: Can't express symbolic location");
2307 /* Output the 88open OCS proscribed text description information.
2310 0 22: info-byte-length (16 or 20 bytes)
2311 0 2: info-alignment (word 2)
2312 1 32: info-protocol (version 1 or 2(pic))
2313 2 32: starting-address (inclusive, not counting prologue)
2314 3 32: ending-address (exclusive, not counting epilog)
2315 4 8: info-variant (version 1 or 3(extended registers))
2316 4 17: register-save-mask (from register 14 to 30)
2318 4 1: return-address-info-discriminant
2319 4 5: frame-address-register
2320 5 32: frame-address-offset
2321 6 32: return-address-info
2322 7 32: register-save-offset
2323 8 16: extended-register-save-mask (x16 - x31)
2324 8 16: extended-register-save-offset (WORDS from register-save-offset) */
2327 output_tdesc (file, offset)
2332 long mask, return_address_info, register_save_offset;
2333 long xmask, xregister_save_offset;
2336 for (mask = 0, i = 0, regno = FIRST_OCS_PRESERVE_REGISTER;
2337 regno <= LAST_OCS_PRESERVE_REGISTER;
2341 if (save_regs[regno])
2348 for (xmask = 0, j = 0, regno = FIRST_OCS_EXTENDED_PRESERVE_REGISTER;
2349 regno <= LAST_OCS_EXTENDED_PRESERVE_REGISTER;
2353 if (save_regs[regno])
2362 if ((nxregs > 0 || nregs > 2) && !save_regs[FRAME_POINTER_REGNUM])
2364 return_address_info = - m88k_stack_size + offset;
2365 register_save_offset = return_address_info - i*4;
2369 return_address_info = 1;
2370 register_save_offset = - m88k_stack_size + offset + 4 - i*4;
2373 xregister_save_offset = - (j * 2 + ((register_save_offset >> 2) & 1));
2377 /* 8:0,22:(20 or 16),2:2 */
2378 fprintf (file, "%s%d,%d", integer_asm_op (4, TRUE),
2379 (((xmask != 0) ? 20 : 16) << 2) | 2,
2382 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_START_PREFIX, m88k_function_number);
2383 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2384 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_END_PREFIX, m88k_function_number);
2385 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2387 fprintf (file, ",0x%x,0x%x,0x%lx,0x%lx",
2388 /* 8:1,17:0x%.3x,1:0,1:%d,5:%d */
2389 (int)(((xmask ? 3 : 1) << (17+1+1+5))
2391 | ((!!save_regs[1]) << 5)
2392 | (frame_pointer_needed
2393 ? FRAME_POINTER_REGNUM
2394 : STACK_POINTER_REGNUM)),
2395 (m88k_stack_size - (frame_pointer_needed ? m88k_fp_offset : 0)),
2396 return_address_info,
2397 register_save_offset);
2399 fprintf (file, ",0x%lx%04lx", xmask, (0xffff & xregister_save_offset));
2405 /* Output assembler code to FILE to increment profiler label # LABELNO
2406 for profiling a function entry. NAME is the mcount function name
2407 (varies), SAVEP indicates whether the parameter registers need to
2408 be saved and restored. */
2411 output_function_profiler (file, labelno, name, savep)
2419 const char *const temp = (savep ? reg_names[2] : reg_names[10]);
2421 /* Remember to update FUNCTION_PROFILER_LENGTH. */
2425 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2426 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2427 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2428 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2429 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2432 ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno);
2435 fprintf (file, "\tor.u\t %s,%s,%shi16(%s#got_rel)\n",
2436 temp, reg_names[0], m88k_pound_sign, &label[1]);
2437 fprintf (file, "\tor\t %s,%s,%slo16(%s#got_rel)\n",
2438 temp, temp, m88k_pound_sign, &label[1]);
2439 sprintf (dbi, "\tld\t %s,%s,%s\n", temp,
2440 reg_names[PIC_OFFSET_TABLE_REGNUM], temp);
2444 sprintf (dbi, "\tld\t %s,%s,%s#got_rel\n", temp,
2445 reg_names[PIC_OFFSET_TABLE_REGNUM], &label[1]);
2449 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n",
2450 temp, reg_names[0], m88k_pound_sign, &label[1]);
2451 sprintf (dbi, "\tor\t %s,%s,%slo16(%s)\n",
2452 temp, temp, m88k_pound_sign, &label[1]);
2456 fprintf (file, "\tbsr.n\t %s#plt\n", name);
2458 fprintf (file, "\tbsr.n\t %s\n", name);
2463 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2464 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2465 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2466 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2467 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2471 /* Output assembler code to FILE to initialize basic-block profiling for
2472 the current module. LABELNO is unique to each instance. */
2475 output_function_block_profiler (file, labelno)
2482 /* Remember to update FUNCTION_BLOCK_PROFILER_LENGTH. */
2484 ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 0);
2485 ASM_GENERATE_INTERNAL_LABEL (label, "LPY", labelno);
2487 /* @@ Need to deal with PIC. I'm not sure what the requirements are on
2488 register usage, so I used r26/r27 to be safe. */
2489 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n", reg_names[27], reg_names[0],
2490 m88k_pound_sign, &block[1]);
2491 fprintf (file, "\tld\t %s,%s,%slo16(%s)\n", reg_names[26], reg_names[27],
2492 m88k_pound_sign, &block[1]);
2493 fprintf (file, "\tbcnd\t %sne0,%s,%s\n",
2494 m88k_pound_sign, reg_names[26], &label[1]);
2495 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2496 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2497 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2498 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2499 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2500 fputs ("\tbsr.n\t ", file);
2501 ASM_OUTPUT_LABELREF (file, "__bb_init_func");
2503 fprintf (file, "\tor\t %s,%s,%slo16(%s)\n", reg_names[2], reg_names[27],
2504 m88k_pound_sign, &block[1]);
2505 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2506 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2507 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2508 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2509 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2510 ASM_OUTPUT_INTERNAL_LABEL (file, "LPY", labelno);
2513 /* Output assembler code to FILE to increment the count associated with
2514 the basic block number BLOCKNO. */
2517 output_block_profiler (file, blockno)
2523 /* Remember to update BLOCK_PROFILER_LENGTH. */
2525 ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 2);
2527 /* @@ Need to deal with PIC. I'm not sure what the requirements are on
2528 register usage, so I used r26/r27 to be safe. */
2529 fprintf (file, "\tor.u\t %s,%s,%shi16(%s+%d)\n", reg_names[27], reg_names[0],
2530 m88k_pound_sign, &block[1], 4 * blockno);
2531 fprintf (file, "\tld\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27],
2532 m88k_pound_sign, &block[1], 4 * blockno);
2533 fprintf (file, "\taddu\t %s,%s,1\n", reg_names[26], reg_names[26]);
2534 fprintf (file, "\tst\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27],
2535 m88k_pound_sign, &block[1], 4 * blockno);
2538 /* Determine whether a function argument is passed in a register, and
2541 The arguments are CUM, which summarizes all the previous
2542 arguments; MODE, the machine mode of the argument; TYPE,
2543 the data type of the argument as a tree node or 0 if that is not known
2544 (which happens for C support library functions); and NAMED,
2545 which is 1 for an ordinary argument and 0 for nameless arguments that
2546 correspond to `...' in the called function's prototype.
2548 The value of the expression should either be a `reg' RTX for the
2549 hard register in which to pass the argument, or zero to pass the
2550 argument on the stack.
2552 On the m88000 the first eight words of args are normally in registers
2553 and the rest are pushed. Double precision floating point must be
2554 double word aligned (and if in a register, starting on an even
2555 register). Structures and unions which are not 4 byte, and word
2556 aligned are passed in memory rather than registers, even if they
2557 would fit completely in the registers under OCS rules.
2559 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2560 For structures that are passed in memory, but could have been
2561 passed in registers, we first load the structure into the
2562 register, and then when the last argument is passed, we store
2563 the registers into the stack locations. This fixes some bugs
2564 where GCC did not expect to have register arguments, followed
2565 by stack arguments, followed by register arguments. */
2568 m88k_function_arg (args_so_far, mode, type, named)
2569 CUMULATIVE_ARGS args_so_far;
2570 enum machine_mode mode;
2572 int named ATTRIBUTE_UNUSED;
2576 if (type != 0 /* undo putting struct in register */
2577 && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
2580 if (mode == BLKmode && TARGET_WARN_PASS_STRUCT)
2581 warning ("argument #%d is a structure", args_so_far + 1);
2583 if ((args_so_far & 1) != 0
2584 && (mode == DImode || mode == DFmode
2585 || (type != 0 && TYPE_ALIGN (type) > 32)))
2590 return (rtx) 0; /* don't put args in registers */
2593 if (type == 0 && mode == BLKmode)
2594 abort (); /* m88k_function_arg argument `type' is NULL for BLKmode. */
2596 bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
2597 words = (bytes + 3) / 4;
2599 if (args_so_far + words > 8)
2600 return (rtx) 0; /* args have exhausted registers */
2602 else if (mode == BLKmode
2603 && (TYPE_ALIGN (type) != BITS_PER_WORD
2604 || bytes != UNITS_PER_WORD))
2607 return gen_rtx_REG (((mode == BLKmode) ? TYPE_MODE (type) : mode),
2611 /* Do what is necessary for `va_start'. We look at the current function
2612 to determine if stdargs or varargs is used and spill as necessary.
2613 We return a pointer to the spill area. */
2616 m88k_builtin_saveregs ()
2619 tree fntype = TREE_TYPE (current_function_decl);
2620 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2621 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2622 != void_type_node)))
2623 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
2626 variable_args_p = 1;
2629 if (GET_CODE (current_function_arg_offset_rtx) == CONST_INT)
2630 fixed = ((INTVAL (current_function_arg_offset_rtx) + argadj)
2633 /* Allocate the register space, and store it as the __va_reg member. */
2634 addr = assign_stack_local (BLKmode, 8 * UNITS_PER_WORD, -1);
2635 set_mem_alias_set (addr, get_varargs_alias_set ());
2636 RTX_UNCHANGING_P (addr) = 1;
2637 RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
2639 /* Now store the incoming registers. */
2641 move_block_from_reg (2 + fixed,
2642 adjust_address (addr, Pmode, fixed * UNITS_PER_WORD),
2644 UNITS_PER_WORD * (8 - fixed));
2646 /* Return the address of the save area, but don't put it in a
2647 register. This fails when not optimizing and produces worse code
2649 return XEXP (addr, 0);
2652 /* Define the `__builtin_va_list' type for the ABI. */
2655 m88k_build_va_list ()
2657 tree field_reg, field_stk, field_arg, int_ptr_type_node, record;
2659 int_ptr_type_node = build_pointer_type (integer_type_node);
2661 record = make_node (RECORD_TYPE);
2663 field_arg = build_decl (FIELD_DECL, get_identifier ("__va_arg"),
2665 field_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"),
2667 field_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),
2670 DECL_FIELD_CONTEXT (field_arg) = record;
2671 DECL_FIELD_CONTEXT (field_stk) = record;
2672 DECL_FIELD_CONTEXT (field_reg) = record;
2674 TYPE_FIELDS (record) = field_arg;
2675 TREE_CHAIN (field_arg) = field_stk;
2676 TREE_CHAIN (field_stk) = field_reg;
2678 layout_type (record);
2682 /* Implement `va_start' for varargs and stdarg. */
2685 m88k_va_start (stdarg_p, valist, nextarg)
2686 int stdarg_p ATTRIBUTE_UNUSED;
2688 rtx nextarg ATTRIBUTE_UNUSED;
2690 tree field_reg, field_stk, field_arg;
2691 tree reg, stk, arg, t;
2693 field_arg = TYPE_FIELDS (va_list_type_node);
2694 field_stk = TREE_CHAIN (field_arg);
2695 field_reg = TREE_CHAIN (field_stk);
2697 arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
2698 stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
2699 reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
2701 /* Fill in the ARG member. */
2703 tree fntype = TREE_TYPE (current_function_decl);
2704 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2705 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2706 != void_type_node)))
2707 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
2710 if (CONSTANT_P (current_function_arg_offset_rtx))
2712 int fixed = (INTVAL (current_function_arg_offset_rtx)
2713 + argadj) / UNITS_PER_WORD;
2715 argsize = build_int_2 (fixed, 0);
2719 argsize = make_tree (integer_type_node,
2720 current_function_arg_offset_rtx);
2721 argsize = fold (build (PLUS_EXPR, integer_type_node, argsize,
2722 build_int_2 (argadj, 0)));
2723 argsize = fold (build (RSHIFT_EXPR, integer_type_node, argsize,
2724 build_int_2 (2, 0)));
2727 t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, argsize);
2728 TREE_SIDE_EFFECTS (t) = 1;
2729 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2732 /* Store the arg pointer in the __va_stk member. */
2733 t = make_tree (TREE_TYPE (stk), virtual_incoming_args_rtx);
2734 t = build (MODIFY_EXPR, TREE_TYPE (stk), stk, t);
2735 TREE_SIDE_EFFECTS (t) = 1;
2736 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2738 /* Tuck the return value from __builtin_saveregs into __va_reg. */
2739 t = make_tree (TREE_TYPE (reg), expand_builtin_saveregs ());
2740 t = build (MODIFY_EXPR, TREE_TYPE (reg), reg, t);
2741 TREE_SIDE_EFFECTS (t) = 1;
2742 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2745 /* Implement `va_arg'. */
2748 m88k_va_arg (valist, type)
2751 tree field_reg, field_stk, field_arg;
2752 tree reg, stk, arg, arg_align, base, t;
2753 int size, wsize, align, reg_p;
2756 field_arg = TYPE_FIELDS (va_list_type_node);
2757 field_stk = TREE_CHAIN (field_arg);
2758 field_reg = TREE_CHAIN (field_stk);
2760 arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
2761 stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
2762 reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
2764 size = int_size_in_bytes (type);
2765 wsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
2766 align = 1 << ((TYPE_ALIGN (type) / BITS_PER_UNIT) >> 3);
2767 reg_p = (AGGREGATE_TYPE_P (type)
2768 ? size == UNITS_PER_WORD && TYPE_ALIGN (type) == BITS_PER_WORD
2769 : size <= 2*UNITS_PER_WORD);
2771 /* Align __va_arg to the (doubleword?) boundary above. */
2772 t = build (PLUS_EXPR, TREE_TYPE (arg), arg, build_int_2 (align - 1, 0));
2773 arg_align = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
2774 arg_align = save_expr (arg_align);
2776 /* Decide if we should read from stack or regs. */
2777 t = build (LT_EXPR, integer_type_node, arg_align, build_int_2 (8, 0));
2778 base = build (COND_EXPR, TREE_TYPE (reg), t, reg, stk);
2780 /* Find the final address. */
2781 t = build (PLUS_EXPR, TREE_TYPE (base), base, arg_align);
2782 addr_rtx = expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
2783 addr_rtx = copy_to_reg (addr_rtx);
2785 /* Increment __va_arg. */
2786 t = build (PLUS_EXPR, TREE_TYPE (arg), arg_align, build_int_2 (wsize, 0));
2787 t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, t);
2788 TREE_SIDE_EFFECTS (t) = 1;
2789 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2794 /* If cmpsi has not been generated, emit code to do the test. Return the
2795 expression describing the test of operator OP. */
2798 emit_test (op, mode)
2800 enum machine_mode mode;
2802 if (m88k_compare_reg == 0)
2803 emit_insn (gen_test (m88k_compare_op0, m88k_compare_op1));
2804 return (gen_rtx (op, mode, m88k_compare_reg, const0_rtx));
2807 /* Determine how to best perform cmpsi/bxx, where cmpsi has a constant
2808 operand. All tests with zero (albeit swapped) and all equality tests
2809 with a constant are done with bcnd. The remaining cases are swapped
2813 emit_bcnd (op, label)
2817 if (m88k_compare_op1 == const0_rtx)
2818 emit_jump_insn (gen_bcnd
2819 (gen_rtx (op, VOIDmode,m88k_compare_op0, const0_rtx),
2821 else if (m88k_compare_op0 == const0_rtx)
2822 emit_jump_insn (gen_bcnd
2823 (gen_rtx (swap_condition (op),
2824 VOIDmode, m88k_compare_op1, const0_rtx),
2826 else if (op != EQ && op != NE)
2827 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2830 rtx zero = gen_reg_rtx (SImode);
2834 if (GET_CODE (m88k_compare_op1) == CONST_INT)
2836 reg = force_reg (SImode, m88k_compare_op0);
2837 constant = m88k_compare_op1;
2841 reg = force_reg (SImode, m88k_compare_op1);
2842 constant = m88k_compare_op0;
2844 value = INTVAL (constant);
2846 /* Perform an arithmetic computation to make the compared-to value
2847 zero, but avoid loosing if the bcnd is later changed into sxx. */
2848 if (SMALL_INTVAL (value))
2849 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2852 if (SMALL_INTVAL (-value))
2853 emit_insn (gen_addsi3 (zero, reg,
2856 emit_insn (gen_xorsi3 (zero, reg, constant));
2858 emit_jump_insn (gen_bcnd (gen_rtx (op, VOIDmode,
2865 /* Print an operand. Recognize special options, documented below. */
2868 print_operand (file, x, code)
2873 enum rtx_code xc = (x ? GET_CODE (x) : UNKNOWN);
2874 register int value = (xc == CONST_INT ? INTVAL (x) : 0);
2875 static int sequencep;
2876 static int reversep;
2880 if (code < 'B' || code > 'E')
2881 output_operand_lossage ("%%R not followed by %%B/C/D/E");
2883 xc = reverse_condition (xc);
2889 case '*': /* addressing base register for PIC */
2890 fputs (reg_names[PIC_OFFSET_TABLE_REGNUM], file); return;
2892 case '#': /* SVR4 pound-sign syntax character (empty if SVR3) */
2893 fputs (m88k_pound_sign, file); return;
2895 case 'V': /* Output a serializing instruction as needed if the operand
2896 (assumed to be a MEM) is a volatile load. */
2897 case 'v': /* ditto for a volatile store. */
2898 if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE)
2900 /* The m88110 implements two FIFO queues, one for loads and
2901 one for stores. These queues mean that loads complete in
2902 their issue order as do stores. An interaction between the
2903 history buffer and the store reservation station ensures
2904 that a store will not bypass load. Finally, a load will not
2905 bypass store, but only when they reference the same address.
2907 To avoid this reordering (a load bypassing a store) for
2908 volatile references, a serializing instruction is output.
2909 We choose the fldcr instruction as it does not serialize on
2910 the m88100 so that -m88000 code will not be degraded.
2912 The mechanism below is completed by having CC_STATUS_INIT set
2913 the code to the unknown value. */
2917 A problem with 88110 4.1 & 4.2 makes the use of fldcr for
2918 this purpose undesirable. Instead we will use tb1, this will
2919 cause serialization on the 88100 but such is life.
2922 static rtx last_addr = 0;
2923 if (code == 'V' /* Only need to serialize before a load. */
2924 && m88k_volatile_code != 'V' /* Loads complete in FIFO order. */
2925 && !(m88k_volatile_code == 'v'
2926 && GET_CODE (XEXP (x, 0)) == LO_SUM
2927 && rtx_equal_p (XEXP (XEXP (x, 0), 1), last_addr)))
2931 "fldcr\t %s,%scr63\n\t",
2933 "fldcr\t %s,%sfcr63\n\t",
2935 reg_names[0], m88k_pound_sign);
2937 "tb1\t 1,%s,0xff\n\t", reg_names[0]);
2939 m88k_volatile_code = code;
2940 last_addr = (GET_CODE (XEXP (x, 0)) == LO_SUM
2941 ? XEXP (XEXP (x, 0), 1) : 0);
2945 case 'X': /* print the upper 16 bits... */
2947 case 'x': /* print the lower 16 bits of the integer constant in hex */
2948 if (xc != CONST_INT)
2949 output_operand_lossage ("invalid %%x/X value");
2950 fprintf (file, "0x%x", value & 0xffff); return;
2952 case 'H': /* print the low 16 bits of the negated integer constant */
2953 if (xc != CONST_INT)
2954 output_operand_lossage ("invalid %%H value");
2956 case 'h': /* print the register or low 16 bits of the integer constant */
2959 if (xc != CONST_INT)
2960 output_operand_lossage ("invalid %%h value");
2961 fprintf (file, "%d", value & 0xffff);
2964 case 'Q': /* print the low 8 bits of the negated integer constant */
2965 if (xc != CONST_INT)
2966 output_operand_lossage ("invalid %%Q value");
2968 case 'q': /* print the register or low 8 bits of the integer constant */
2971 if (xc != CONST_INT)
2972 output_operand_lossage ("invalid %%q value");
2973 fprintf (file, "%d", value & 0xff);
2976 case 'w': /* print the integer constant (X == 32 ? 0 : 32 - X) */
2977 if (xc != CONST_INT)
2978 output_operand_lossage ("invalid %%o value");
2979 fprintf (file, "%d", value == 32 ? 0 : 32 - value);
2982 case 'p': /* print the logarithm of the integer constant */
2984 || (value = exact_log2 (value)) < 0)
2985 output_operand_lossage ("invalid %%p value");
2986 fprintf (file, "%d", value);
2989 case 'S': /* compliment the value and then... */
2991 case 's': /* print the width and offset values forming the integer
2992 constant with a SET instruction. See integer_ok_for_set. */
2994 register unsigned mask, uval = value;
2995 register int top, bottom;
2997 if (xc != CONST_INT)
2998 output_operand_lossage ("invalid %%s/S value");
2999 /* All the "one" bits must be contiguous. If so, MASK will be
3000 a power of two or zero. */
3001 mask = (uval | (uval - 1)) + 1;
3002 if (!(uval && POWER_OF_2_or_0 (mask)))
3003 output_operand_lossage ("invalid %%s/S value");
3004 top = mask ? exact_log2 (mask) : 32;
3005 bottom = exact_log2 (uval & ~(uval - 1));
3006 fprintf (file,"%d<%d>", top - bottom, bottom);
3010 case 'P': /* print nothing if pc_rtx; output label_ref */
3011 if (xc == LABEL_REF)
3012 output_addr_const (file, x);
3014 output_operand_lossage ("invalid %%P operand");
3017 case 'L': /* print 0 or 1 if operand is label_ref and then... */
3018 fputc (xc == LABEL_REF ? '1' : '0', file);
3019 case '.': /* print .n if delay slot is used */
3020 fputs ((final_sequence
3021 && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
3022 ? ".n\t" : "\t", file);
3025 case '!': /* Reverse the following condition. */
3029 case 'R': /* reverse the condition of the next print_operand
3030 if operand is a label_ref. */
3032 reversep = (xc == LABEL_REF);
3035 case 'B': /* bcnd branch values */
3036 fputs (m88k_pound_sign, file);
3039 case EQ: fputs ("eq0", file); return;
3040 case NE: fputs ("ne0", file); return;
3041 case GT: fputs ("gt0", file); return;
3042 case LE: fputs ("le0", file); return;
3043 case LT: fputs ("lt0", file); return;
3044 case GE: fputs ("ge0", file); return;
3045 default: output_operand_lossage ("invalid %%B value");
3048 case 'C': /* bb0/bb1 branch values for comparisons */
3049 fputs (m88k_pound_sign, file);
3052 case EQ: fputs ("eq", file); return;
3053 case NE: fputs ("ne", file); return;
3054 case GT: fputs ("gt", file); return;
3055 case LE: fputs ("le", file); return;
3056 case LT: fputs ("lt", file); return;
3057 case GE: fputs ("ge", file); return;
3058 case GTU: fputs ("hi", file); return;
3059 case LEU: fputs ("ls", file); return;
3060 case LTU: fputs ("lo", file); return;
3061 case GEU: fputs ("hs", file); return;
3062 default: output_operand_lossage ("invalid %%C value");
3065 case 'D': /* bcnd branch values for float comparisons */
3068 case EQ: fputs ("0xa", file); return;
3069 case NE: fputs ("0x5", file); return;
3070 case GT: fputs (m88k_pound_sign, file);
3071 fputs ("gt0", file); return;
3072 case LE: fputs ("0xe", file); return;
3073 case LT: fputs ("0x4", file); return;
3074 case GE: fputs ("0xb", file); return;
3075 default: output_operand_lossage ("invalid %%D value");
3078 case 'E': /* bcnd branch values for special integers */
3081 case EQ: fputs ("0x8", file); return;
3082 case NE: fputs ("0x7", file); return;
3083 default: output_operand_lossage ("invalid %%E value");
3086 case 'd': /* second register of a two register pair */
3088 output_operand_lossage ("`%%d' operand isn't a register");
3089 fputs (reg_names[REGNO (x) + 1], file);
3092 case 'r': /* an immediate 0 should be represented as `r0' */
3093 if (x == const0_rtx)
3095 fputs (reg_names[0], file);
3099 output_operand_lossage ("invalid %%r value");
3105 if (REGNO (x) == ARG_POINTER_REGNUM)
3106 output_operand_lossage ("operand is r0");
3108 fputs (reg_names[REGNO (x)], file);
3110 else if (xc == PLUS)
3113 output_address (XEXP (x, 0));
3114 else if (flag_pic && xc == UNSPEC)
3116 output_addr_const (file, XVECEXP (x, 0, 0));
3117 fputs ("#got_rel", file);
3119 else if (xc == CONST_DOUBLE)
3120 output_operand_lossage ("operand is const_double");
3122 output_addr_const (file, x);
3125 case 'g': /* append #got_rel as needed */
3126 if (flag_pic && (xc == SYMBOL_REF || xc == LABEL_REF))
3128 output_addr_const (file, x);
3129 fputs ("#got_rel", file);
3134 case 'a': /* (standard), assume operand is an address */
3135 case 'c': /* (standard), assume operand is an immediate value */
3136 case 'l': /* (standard), assume operand is a label_ref */
3137 case 'n': /* (standard), like %c, except negate first */
3139 output_operand_lossage ("invalid code");
3144 print_operand_address (file, addr)
3148 register rtx reg0, reg1, temp;
3150 switch (GET_CODE (addr))
3153 if (REGNO (addr) == ARG_POINTER_REGNUM)
3156 fprintf (file, "%s,%s", reg_names[0], reg_names [REGNO (addr)]);
3160 fprintf (file, "%s,%slo16(",
3161 reg_names[REGNO (XEXP (addr, 0))], m88k_pound_sign);
3162 output_addr_const (file, XEXP (addr, 1));
3167 reg0 = XEXP (addr, 0);
3168 reg1 = XEXP (addr, 1);
3169 if (GET_CODE (reg0) == MULT || GET_CODE (reg0) == CONST_INT)
3176 if ((REG_P (reg0) && REGNO (reg0) == ARG_POINTER_REGNUM)
3177 || (REG_P (reg1) && REGNO (reg1) == ARG_POINTER_REGNUM))
3180 else if (REG_P (reg0))
3183 fprintf (file, "%s,%s",
3184 reg_names [REGNO (reg0)], reg_names [REGNO (reg1)]);
3186 else if (GET_CODE (reg1) == CONST_INT)
3187 fprintf (file, "%s,%d",
3188 reg_names [REGNO (reg0)], INTVAL (reg1));
3190 else if (GET_CODE (reg1) == MULT)
3192 rtx mreg = XEXP (reg1, 0);
3193 if (REGNO (mreg) == ARG_POINTER_REGNUM)
3196 fprintf (file, "%s[%s]", reg_names[REGNO (reg0)],
3197 reg_names[REGNO (mreg)]);
3200 else if (GET_CODE (reg1) == ZERO_EXTRACT)
3202 fprintf (file, "%s,%slo16(",
3203 reg_names[REGNO (reg0)], m88k_pound_sign);
3204 output_addr_const (file, XEXP (reg1, 0));
3210 fprintf (file, "%s,", reg_names[REGNO (reg0)]);
3211 output_addr_const (file, reg1);
3212 fputs ("#got_rel", file);
3222 if (REGNO (XEXP (addr, 0)) == ARG_POINTER_REGNUM)
3225 fprintf (file, "%s[%s]",
3226 reg_names[0], reg_names[REGNO (XEXP (addr, 0))]);
3230 fprintf (file, "%s,%d", reg_names[0], INTVAL (addr));
3234 fprintf (file, "%s,", reg_names[0]);
3235 if (SHORT_ADDRESS_P (addr, temp))
3237 fprintf (file, "%siw16(", m88k_pound_sign);
3238 output_addr_const (file, addr);
3242 output_addr_const (file, addr);
3246 /* Return true if X is an address which needs a temporary register when
3247 reloaded while generating PIC code. */
3250 pic_address_needs_scratch (x)
3253 /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */
3254 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
3255 && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
3256 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
3257 && ! ADD_INT (XEXP (XEXP (x, 0), 1)))
3263 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
3264 reference and a constant. */
3267 symbolic_operand (op, mode)
3269 enum machine_mode mode;
3271 switch (GET_CODE (op))
3279 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
3280 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
3281 && GET_CODE (XEXP (op, 1)) == CONST_INT);
3283 /* ??? This clause seems to be irrelevant. */
3285 return GET_MODE (op) == mode;
3292 #if defined (CTOR_LIST_BEGIN) && !defined (OBJECT_FORMAT_ELF)
3294 m88k_svr3_asm_out_constructor (symbol, priority)
3296 int priority ATTRIBUTE_UNUSED;
3298 const char *name = XSTR (symbol, 0);
3301 fprintf (asm_out_file, "\tor.u\t r13,r0,hi16(");
3302 assemble_name (asm_out_file, name);
3303 fprintf (asm_out_file, ")\n\tor\t r13,r13,lo16(");
3304 assemble_name (asm_out_file, name);
3305 fprintf (asm_out_file, ")\n\tsubu\t r31,r31,%d\n\tst\t r13,r31,%d\n",
3306 STACK_BOUNDARY / BITS_PER_UNIT, REG_PARM_STACK_SPACE (0));
3310 m88k_svr3_asm_out_destructor (symbol, priority)
3312 int priority ATTRIBUTE_UNUSED;
3317 assemble_integer (symbol, UNITS_PER_WORD, BITS_PER_WORD, 1);
3318 for (i = 1; i < 4; i++)
3319 assemble_integer (constm1_rtx, UNITS_PER_WORD, BITS_PER_WORD, 1);
3321 #endif /* INIT_SECTION_ASM_OP && ! OBJECT_FORMAT_ELF */
3324 m88k_select_section (decl, reloc, align)
3327 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
3329 if (TREE_CODE (decl) == STRING_CST)
3331 if (! flag_writable_strings)
3333 else if (TREE_STRING_LENGTH (decl) <= m88k_gp_threshold)
3338 else if (TREE_CODE (decl) == VAR_DECL)
3340 if (SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)))
3342 else if ((flag_pic && reloc)
3343 || !TREE_READONLY (decl) || TREE_SIDE_EFFECTS (decl)
3344 || !DECL_INITIAL (decl)
3345 || (DECL_INITIAL (decl) != error_mark_node
3346 && !TREE_CONSTANT (DECL_INITIAL (decl))))
3355 /* Adjust the cost of INSN based on the relationship between INSN that
3356 is dependent on DEP_INSN through the dependence LINK. The default
3357 is to make no adjustment to COST.
3359 On the m88k, ignore the cost of anti- and output-dependencies. On
3360 the m88100, a store can issue two cycles before the value (not the
3361 address) has finished computing. */
3364 m88k_adjust_cost (insn, link, dep, cost)
3370 if (REG_NOTE_KIND (link) != 0)
3371 return 0; /* Anti or output dependence. */
3374 && recog_memoized (insn) >= 0
3375 && get_attr_type (insn) == TYPE_STORE
3376 && SET_SRC (PATTERN (insn)) == SET_DEST (PATTERN (dep)))
3377 return cost - 4; /* 88110 store reservation station. */