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));
76 static void m88k_encode_section_info PARAMS ((tree, int));
78 /* Initialize the GCC target structure. */
79 #undef TARGET_ASM_BYTE_OP
80 #define TARGET_ASM_BYTE_OP "\tbyte\t"
81 #undef TARGET_ASM_ALIGNED_HI_OP
82 #define TARGET_ASM_ALIGNED_HI_OP "\thalf\t"
83 #undef TARGET_ASM_ALIGNED_SI_OP
84 #define TARGET_ASM_ALIGNED_SI_OP "\tword\t"
85 #undef TARGET_ASM_UNALIGNED_HI_OP
86 #define TARGET_ASM_UNALIGNED_HI_OP "\tuahalf\t"
87 #undef TARGET_ASM_UNALIGNED_SI_OP
88 #define TARGET_ASM_UNALIGNED_SI_OP "\tuaword\t"
90 #undef TARGET_ASM_FUNCTION_PROLOGUE
91 #define TARGET_ASM_FUNCTION_PROLOGUE m88k_output_function_prologue
92 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
93 #define TARGET_ASM_FUNCTION_END_PROLOGUE m88k_output_function_end_prologue
94 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
95 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE m88k_output_function_begin_epilogue
96 #undef TARGET_ASM_FUNCTION_EPILOGUE
97 #define TARGET_ASM_FUNCTION_EPILOGUE m88k_output_function_epilogue
99 #undef TARGET_SCHED_ADJUST_COST
100 #define TARGET_SCHED_ADJUST_COST m88k_adjust_cost
102 #undef TARGET_ENCODE_SECTION_INFO
103 #define TARGET_ENCODE_SECTION_INFO m88k_encode_section_info
105 struct gcc_target targetm = TARGET_INITIALIZER;
107 /* Determine what instructions are needed to manufacture the integer VALUE
108 in the given MODE. */
110 enum m88k_instruction
111 classify_integer (mode, value)
112 enum machine_mode mode;
117 else if (SMALL_INTVAL (value))
119 else if (SMALL_INTVAL (-value))
121 else if (mode == HImode)
123 else if (mode == QImode)
125 else if ((value & 0xffff) == 0)
126 return m88k_oru_hi16;
127 else if (integer_ok_for_set (value))
133 /* Return the bit number in a compare word corresponding to CONDITION. */
136 condition_value (condition)
139 switch (GET_CODE (condition))
156 integer_ok_for_set (value)
157 register unsigned value;
159 /* All the "one" bits must be contiguous. If so, MASK + 1 will be
160 a power of two or zero. */
161 register unsigned mask = (value | (value - 1));
162 return (value && POWER_OF_2_or_0 (mask + 1));
166 output_load_const_int (mode, operands)
167 enum machine_mode mode;
170 static const char *const patterns[] =
178 "or.u %0,%#r0,%X1\n\tor %0,%0,%x1",
181 if (! REG_P (operands[0])
182 || GET_CODE (operands[1]) != CONST_INT)
184 return patterns[classify_integer (mode, INTVAL (operands[1]))];
187 /* These next two routines assume that floating point numbers are represented
188 in a manner which is consistent between host and target machines. */
191 output_load_const_float (operands)
194 /* These can return 0 under some circumstances when cross-compiling. */
195 operands[0] = operand_subword (operands[0], 0, 0, SFmode);
196 operands[1] = operand_subword (operands[1], 0, 0, SFmode);
198 return output_load_const_int (SImode, operands);
202 output_load_const_double (operands)
207 /* These can return zero on some cross-compilers, but there's nothing
208 we can do about it. */
209 latehalf[0] = operand_subword (operands[0], 1, 0, DFmode);
210 latehalf[1] = operand_subword (operands[1], 1, 0, DFmode);
212 operands[0] = operand_subword (operands[0], 0, 0, DFmode);
213 operands[1] = operand_subword (operands[1], 0, 0, DFmode);
215 output_asm_insn (output_load_const_int (SImode, operands), operands);
217 operands[0] = latehalf[0];
218 operands[1] = latehalf[1];
220 return output_load_const_int (SImode, operands);
224 output_load_const_dimode (operands)
229 latehalf[0] = operand_subword (operands[0], 1, 0, DImode);
230 latehalf[1] = operand_subword (operands[1], 1, 0, DImode);
232 operands[0] = operand_subword (operands[0], 0, 0, DImode);
233 operands[1] = operand_subword (operands[1], 0, 0, DImode);
235 output_asm_insn (output_load_const_int (SImode, operands), operands);
237 operands[0] = latehalf[0];
238 operands[1] = latehalf[1];
240 return output_load_const_int (SImode, operands);
243 /* Emit insns to move operands[1] into operands[0].
245 Return 1 if we have written out everything that needs to be done to
246 do the move. Otherwise, return 0 and the caller will emit the move
249 SCRATCH if nonzero can be used as a scratch register for the move
250 operation. It is provided by a SECONDARY_RELOAD_* macro if needed. */
253 emit_move_sequence (operands, mode, scratch)
255 enum machine_mode mode;
258 register rtx operand0 = operands[0];
259 register rtx operand1 = operands[1];
261 if (CONSTANT_P (operand1) && flag_pic
262 && pic_address_needs_scratch (operand1))
263 operands[1] = operand1 = legitimize_address (1, operand1, 0, 0);
265 /* Handle most common case first: storing into a register. */
266 if (register_operand (operand0, mode))
268 if (register_operand (operand1, mode)
269 || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
270 || GET_CODE (operand1) == HIGH
271 /* Only `general_operands' can come here, so MEM is ok. */
272 || GET_CODE (operand1) == MEM)
274 /* Run this case quickly. */
275 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
279 else if (GET_CODE (operand0) == MEM)
281 if (register_operand (operand1, mode)
282 || (operand1 == const0_rtx && GET_MODE_SIZE (mode) <= UNITS_PER_WORD))
284 /* Run this case quickly. */
285 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
288 if (! reload_in_progress && ! reload_completed)
290 operands[0] = validize_mem (operand0);
291 operands[1] = operand1 = force_reg (mode, operand1);
295 /* Simplify the source if we need to. */
296 if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
298 if (GET_CODE (operand1) != CONST_INT
299 && GET_CODE (operand1) != CONST_DOUBLE)
301 rtx temp = ((reload_in_progress || reload_completed)
303 operands[1] = legitimize_address (flag_pic
304 && symbolic_address_p (operand1),
305 operand1, temp, scratch);
307 operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
311 /* Now have insn-emit do whatever it normally does. */
315 /* Return a legitimate reference for ORIG (either an address or a MEM)
316 using the register REG. If PIC and the address is already
317 position-independent, use ORIG. Newly generated position-independent
318 addresses go into a reg. This is REG if nonzero, otherwise we
319 allocate register(s) as necessary. If this is called during reload,
320 and we need a second temp register, then we use SCRATCH, which is
321 provided via the SECONDARY_INPUT_RELOAD_CLASS mechanism. */
324 legitimize_address (pic, orig, reg, scratch)
330 rtx addr = (GET_CODE (orig) == MEM ? XEXP (orig, 0) : orig);
336 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
340 if (reload_in_progress || reload_completed)
343 reg = gen_reg_rtx (Pmode);
348 /* If not during reload, allocate another temp reg here for
349 loading in the address, so that these instructions can be
350 optimized properly. */
351 temp = ((reload_in_progress || reload_completed)
352 ? reg : gen_reg_rtx (Pmode));
354 emit_insn (gen_rtx_SET
356 gen_rtx_HIGH (SImode,
357 gen_rtx_UNSPEC (SImode,
361 emit_insn (gen_rtx_SET
363 gen_rtx_LO_SUM (SImode, temp,
364 gen_rtx_UNSPEC (SImode,
370 new = gen_rtx_MEM (Pmode,
371 gen_rtx_PLUS (SImode,
372 pic_offset_table_rtx, addr));
374 current_function_uses_pic_offset_table = 1;
375 RTX_UNCHANGING_P (new) = 1;
376 insn = emit_move_insn (reg, new);
377 /* Put a REG_EQUAL note on this insn, so that it can be optimized
379 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
383 else if (GET_CODE (addr) == CONST)
387 if (GET_CODE (XEXP (addr, 0)) == PLUS
388 && XEXP (XEXP (addr, 0), 0) == pic_offset_table_rtx)
393 if (reload_in_progress || reload_completed)
396 reg = gen_reg_rtx (Pmode);
399 if (GET_CODE (XEXP (addr, 0)) != PLUS) abort ();
401 base = legitimize_address (1, XEXP (XEXP (addr, 0), 0), reg, 0);
402 addr = legitimize_address (1, XEXP (XEXP (addr, 0), 1),
403 base == reg ? 0 : reg, 0);
405 if (GET_CODE (addr) == CONST_INT)
408 return plus_constant (base, INTVAL (addr));
409 else if (! reload_in_progress && ! reload_completed)
410 addr = force_reg (Pmode, addr);
411 /* We can't create any new registers during reload, so use the
412 SCRATCH reg provided by the reload_insi pattern. */
415 emit_move_insn (scratch, addr);
419 /* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS
420 macro needs to be adjusted so that a scratch reg is provided
424 new = gen_rtx_PLUS (SImode, base, addr);
425 /* Should we set special REG_NOTEs here? */
428 else if (! SHORT_ADDRESS_P (addr, temp))
432 if (reload_in_progress || reload_completed)
435 reg = gen_reg_rtx (Pmode);
438 emit_insn (gen_rtx_SET (VOIDmode,
439 reg, gen_rtx_HIGH (SImode, addr)));
440 new = gen_rtx_LO_SUM (SImode, reg, addr);
444 && GET_CODE (orig) == MEM)
446 new = gen_rtx_MEM (GET_MODE (orig), new);
447 MEM_COPY_ATTRIBUTES (new, orig);
452 /* Support functions for code to emit a block move. There are four methods
453 used to perform the block move:
455 + call the looping library function, e.g. __movstrSI64n8
456 + call a non-looping library function, e.g. __movstrHI15x11
457 + produce an inline sequence of ld/st instructions
459 The parameters below describe the library functions produced by
462 #define MOVSTR_LOOP 64 /* __movstrSI64n68 .. __movstrSI64n8 */
463 #define MOVSTR_QI 16 /* __movstrQI16x16 .. __movstrQI16x2 */
464 #define MOVSTR_HI 48 /* __movstrHI48x48 .. __movstrHI48x4 */
465 #define MOVSTR_SI 96 /* __movstrSI96x96 .. __movstrSI96x8 */
466 #define MOVSTR_DI 96 /* __movstrDI96x96 .. __movstrDI96x16 */
467 #define MOVSTR_ODD_HI 16 /* __movstrHI15x15 .. __movstrHI15x5 */
468 #define MOVSTR_ODD_SI 48 /* __movstrSI47x47 .. __movstrSI47x11,
469 __movstrSI46x46 .. __movstrSI46x10,
470 __movstrSI45x45 .. __movstrSI45x9 */
471 #define MOVSTR_ODD_DI 48 /* __movstrDI47x47 .. __movstrDI47x23,
472 __movstrDI46x46 .. __movstrDI46x22,
473 __movstrDI45x45 .. __movstrDI45x21,
474 __movstrDI44x44 .. __movstrDI44x20,
475 __movstrDI43x43 .. __movstrDI43x19,
476 __movstrDI42x42 .. __movstrDI42x18,
477 __movstrDI41x41 .. __movstrDI41x17 */
479 /* Limits for using the non-looping movstr functions. For the m88100
480 processor, we assume the source and destination are word aligned.
481 The QImode and HImode limits are the break even points where memcpy
482 does just as well and beyond which memcpy does better. For the
483 m88110, we tend to assume double word alignment, but also analyze
484 the word aligned cases. The analysis is complicated because memcpy
485 may use the cache control instructions for better performance. */
487 #define MOVSTR_QI_LIMIT_88100 13
488 #define MOVSTR_HI_LIMIT_88100 38
489 #define MOVSTR_SI_LIMIT_88100 MOVSTR_SI
490 #define MOVSTR_DI_LIMIT_88100 MOVSTR_SI
492 #define MOVSTR_QI_LIMIT_88000 16
493 #define MOVSTR_HI_LIMIT_88000 38
494 #define MOVSTR_SI_LIMIT_88000 72
495 #define MOVSTR_DI_LIMIT_88000 72
497 #define MOVSTR_QI_LIMIT_88110 16
498 #define MOVSTR_HI_LIMIT_88110 38
499 #define MOVSTR_SI_LIMIT_88110 72
500 #define MOVSTR_DI_LIMIT_88110 72
502 static const enum machine_mode mode_from_align[] =
503 {VOIDmode, QImode, HImode, VOIDmode, SImode,
504 VOIDmode, VOIDmode, VOIDmode, DImode};
505 static const int max_from_align[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI,
507 static const int all_from_align[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0,
508 MOVSTR_ODD_SI, 0, 0, 0, MOVSTR_ODD_DI};
510 static const int best_from_align[3][9] = {
511 {0, MOVSTR_QI_LIMIT_88100, MOVSTR_HI_LIMIT_88100, 0, MOVSTR_SI_LIMIT_88100,
512 0, 0, 0, MOVSTR_DI_LIMIT_88100},
513 {0, MOVSTR_QI_LIMIT_88110, MOVSTR_HI_LIMIT_88110, 0, MOVSTR_SI_LIMIT_88110,
514 0, 0, 0, MOVSTR_DI_LIMIT_88110},
515 {0, MOVSTR_QI_LIMIT_88000, MOVSTR_HI_LIMIT_88000, 0, MOVSTR_SI_LIMIT_88000,
516 0, 0, 0, MOVSTR_DI_LIMIT_88000}
519 static void block_move_loop PARAMS ((rtx, rtx, rtx, rtx, int, int));
520 static void block_move_no_loop PARAMS ((rtx, rtx, rtx, rtx, int, int));
521 static void block_move_sequence PARAMS ((rtx, rtx, rtx, rtx, int, int, int));
522 static void output_short_branch_defs PARAMS ((FILE *));
523 static int output_option PARAMS ((FILE *, const char *, const char *,
524 const char *, const char *, int, int));
526 /* Emit code to perform a block move. Choose the best method.
528 OPERANDS[0] is the destination.
529 OPERANDS[1] is the source.
530 OPERANDS[2] is the size.
531 OPERANDS[3] is the alignment safe to use. */
534 expand_block_move (dest_mem, src_mem, operands)
539 int align = INTVAL (operands[3]);
540 int constp = (GET_CODE (operands[2]) == CONST_INT);
541 int bytes = (constp ? INTVAL (operands[2]) : 0);
542 int target = (int) m88k_cpu;
544 if (! (PROCESSOR_M88100 == 0
545 && PROCESSOR_M88110 == 1
546 && PROCESSOR_M88000 == 2))
549 if (constp && bytes <= 0)
552 /* Determine machine mode to do move with. */
553 if (align > 4 && !TARGET_88110)
555 else if (align <= 0 || align == 3)
556 abort (); /* block move invalid alignment. */
558 if (constp && bytes <= 3 * align)
559 block_move_sequence (operands[0], dest_mem, operands[1], src_mem,
562 else if (constp && bytes <= best_from_align[target][align])
563 block_move_no_loop (operands[0], dest_mem, operands[1], src_mem,
566 else if (constp && align == 4 && TARGET_88100)
567 block_move_loop (operands[0], dest_mem, operands[1], src_mem,
572 #ifdef TARGET_MEM_FUNCTIONS
573 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "memcpy"), 0,
577 convert_to_mode (TYPE_MODE (sizetype), operands[2],
578 TREE_UNSIGNED (sizetype)),
579 TYPE_MODE (sizetype));
581 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "bcopy"), 0,
585 convert_to_mode (TYPE_MODE (integer_type_node),
587 TREE_UNSIGNED (integer_type_node)),
588 TYPE_MODE (integer_type_node));
593 /* Emit code to perform a block move by calling a looping movstr library
594 function. SIZE and ALIGN are known constants. DEST and SRC are
598 block_move_loop (dest, dest_mem, src, src_mem, size, align)
604 enum machine_mode mode;
613 /* Determine machine mode to do move with. */
617 /* Determine the structure of the loop. */
618 count = size / MOVSTR_LOOP;
619 units = (size - count * MOVSTR_LOOP) / align;
624 units += MOVSTR_LOOP / align;
629 block_move_no_loop (dest, dest_mem, src, src_mem, size, align);
633 remainder = size - count * MOVSTR_LOOP - units * align;
635 mode = mode_from_align[align];
636 sprintf (entry, "__movstr%s%dn%d",
637 GET_MODE_NAME (mode), MOVSTR_LOOP, units * align);
638 entry_name = get_identifier (entry);
640 offset_rtx = GEN_INT (MOVSTR_LOOP + (1 - units) * align);
642 value_rtx = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode,
644 gen_rtx_REG (Pmode, 3),
646 MEM_COPY_ATTRIBUTES (value_rtx, src_mem);
648 emit_insn (gen_call_movstrsi_loop
649 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)),
650 dest, src, offset_rtx, value_rtx,
651 gen_rtx_REG (mode, ((units & 1) ? 4 : 5)),
655 block_move_sequence (gen_rtx_REG (Pmode, 2), dest_mem,
656 gen_rtx_REG (Pmode, 3), src_mem,
657 remainder, align, MOVSTR_LOOP + align);
660 /* Emit code to perform a block move by calling a non-looping library
661 function. SIZE and ALIGN are known constants. DEST and SRC are
662 registers. OFFSET is the known starting point for the output pattern. */
665 block_move_no_loop (dest, dest_mem, src, src_mem, size, align)
671 enum machine_mode mode = mode_from_align[align];
672 int units = size / align;
673 int remainder = size - units * align;
681 if (remainder && size <= all_from_align[align])
683 most = all_from_align[align] - (align - remainder);
688 most = max_from_align[align];
691 sprintf (entry, "__movstr%s%dx%d",
692 GET_MODE_NAME (mode), most, size - remainder);
693 entry_name = get_identifier (entry);
695 offset_rtx = GEN_INT (most - (size - remainder));
697 value_rtx = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode,
699 gen_rtx_REG (Pmode, 3),
702 MEM_COPY_ATTRIBUTES (value_rtx, src_mem);
704 value_reg = ((((most - (size - remainder)) / align) & 1) == 0
705 ? (align == 8 ? 6 : 5) : 4);
707 emit_insn (gen_call_block_move
708 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)),
709 dest, src, offset_rtx, value_rtx,
710 gen_rtx_REG (mode, value_reg)));
713 block_move_sequence (gen_rtx_REG (Pmode, 2), dest_mem,
714 gen_rtx_REG (Pmode, 3), src_mem,
715 remainder, align, most);
718 /* Emit code to perform a block move with an offset sequence of ld/st
719 instructions (..., ld 0, st 1, ld 1, st 0, ...). SIZE and ALIGN are
720 known constants. DEST and SRC are registers. OFFSET is the known
721 starting point for the output pattern. */
724 block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset)
732 enum machine_mode mode[2];
737 int offset_ld = offset;
738 int offset_st = offset;
740 active[0] = active[1] = FALSE;
742 /* Establish parameters for the first load and for the second load if
743 it is known to be the same mode as the first. */
744 amount[0] = amount[1] = align;
745 mode[0] = mode_from_align[align];
746 temp[0] = gen_reg_rtx (mode[0]);
747 if (size >= 2 * align)
750 temp[1] = gen_reg_rtx (mode[1]);
761 /* Change modes as the sequence tails off. */
762 if (size < amount[next])
764 amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1));
765 mode[next] = mode_from_align[amount[next]];
766 temp[next] = gen_reg_rtx (mode[next]);
768 size -= amount[next];
769 srcp = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode[next] : BLKmode,
770 plus_constant (src, offset_ld));
772 MEM_COPY_ATTRIBUTES (srcp, src_mem);
773 emit_insn (gen_rtx_SET (VOIDmode, temp[next], srcp));
774 offset_ld += amount[next];
780 active[phase] = FALSE;
782 = gen_rtx_MEM (MEM_IN_STRUCT_P (dest_mem) ? mode[phase] : BLKmode,
783 plus_constant (dest, offset_st));
785 MEM_COPY_ATTRIBUTES (dstp, dest_mem);
786 emit_insn (gen_rtx_SET (VOIDmode, dstp, temp[phase]));
787 offset_st += amount[phase];
790 while (active[next]);
793 /* Emit the code to do an AND operation. */
796 output_and (operands)
801 if (REG_P (operands[2]))
802 return "and %0,%1,%2";
804 value = INTVAL (operands[2]);
805 if (SMALL_INTVAL (value))
806 return "mask %0,%1,%2";
807 else if ((value & 0xffff0000) == 0xffff0000)
808 return "and %0,%1,%x2";
809 else if ((value & 0xffff) == 0xffff)
810 return "and.u %0,%1,%X2";
811 else if ((value & 0xffff) == 0)
812 return "mask.u %0,%1,%X2";
813 else if (integer_ok_for_set (~value))
814 return "clr %0,%1,%S2";
816 return "and.u %0,%1,%X2\n\tand %0,%0,%x2";
819 /* Emit the code to do an inclusive OR operation. */
822 output_ior (operands)
827 if (REG_P (operands[2]))
828 return "or %0,%1,%2";
830 value = INTVAL (operands[2]);
831 if (SMALL_INTVAL (value))
832 return "or %0,%1,%2";
833 else if ((value & 0xffff) == 0)
834 return "or.u %0,%1,%X2";
835 else if (integer_ok_for_set (value))
836 return "set %0,%1,%s2";
838 return "or.u %0,%1,%X2\n\tor %0,%0,%x2";
841 /* Emit the instructions for doing an XOR. */
844 output_xor (operands)
849 if (REG_P (operands[2]))
850 return "xor %0,%1,%2";
852 value = INTVAL (operands[2]);
853 if (SMALL_INTVAL (value))
854 return "xor %0,%1,%2";
855 else if ((value & 0xffff) == 0)
856 return "xor.u %0,%1,%X2";
858 return "xor.u %0,%1,%X2\n\txor %0,%0,%x2";
861 /* Output a call. Normally this is just bsr or jsr, but this also deals with
862 accomplishing a branch after the call by incrementing r1. This requires
863 that various assembler bugs be accommodated. The 4.30 DG/UX assembler
864 requires that forward references not occur when computing the difference of
865 two labels. The [version?] Motorola assembler computes a word difference.
866 No doubt there's more to come!
868 It would seem the same idea could be used to tail call, but in this case,
869 the epilogue will be non-null. */
871 static rtx sb_name = 0;
872 static rtx sb_high = 0;
873 static rtx sb_low = 0;
876 output_call (operands, addr)
886 /* This can be generalized, but there is currently no need. */
887 if (XVECLEN (final_sequence, 0) != 2)
890 /* The address of interior insns is not computed, so use the sequence. */
891 seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
892 jump = XVECEXP (final_sequence, 0, 1);
893 if (GET_CODE (jump) == JUMP_INSN)
897 rtx dest = XEXP (SET_SRC (PATTERN (jump)), 0);
898 int delta = 4 * (INSN_ADDRESSES (INSN_UID (dest))
899 - INSN_ADDRESSES (INSN_UID (seq_insn))
901 #if (MONITOR_GCC & 0x2) /* How often do long branches happen? */
902 if ((unsigned) (delta + 0x8000) >= 0x10000)
903 warning ("internal gcc monitor: short-branch(%x)", delta);
906 /* Delete the jump. */
907 PUT_CODE (jump, NOTE);
908 NOTE_LINE_NUMBER (jump) = NOTE_INSN_DELETED;
909 NOTE_SOURCE_FILE (jump) = 0;
911 /* We only do this optimization if -O2, modifying the value of
912 r1 in the delay slot confuses debuggers and profilers on some
915 If we loose, we must use the non-delay form. This is unlikely
916 to ever happen. If it becomes a problem, claim that a call
917 has two delay slots and only the second can be filled with
920 The 88110 can lose when a jsr.n r1 is issued and a page fault
921 occurs accessing the delay slot. So don't use jsr.n form when
924 #ifdef AS_BUG_IMMEDIATE_LABEL /* The assembler restricts immediate values. */
926 || ! ADD_INTVAL (delta * 2)
929 || ! ADD_INTVAL (delta)
931 || (REG_P (addr) && REGNO (addr) == 1))
937 ? "bsr %0#plt\n\tbr %l1"
938 : "bsr %0\n\tbr %l1"));
941 /* Output the short branch form. */
942 output_asm_insn ((REG_P (addr)
944 : (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")),
949 ? "subu %#r1,%#r1,.-%l0+4"
950 : "addu %#r1,%#r1,%l0-.-4");
953 operands[0] = gen_label_rtx ();
954 operands[1] = gen_label_rtx ();
959 last = "subu %#r1,%#r1,%l0\n%l1:";
965 last = "addu %#r1,%#r1,%l0\n%l1:";
968 /* Record the values to be computed later as "def name,high-low". */
969 sb_name = gen_rtx_EXPR_LIST (VOIDmode, operands[0], sb_name);
970 sb_high = gen_rtx_EXPR_LIST (VOIDmode, high, sb_high);
971 sb_low = gen_rtx_EXPR_LIST (VOIDmode, low, sb_low);
972 #endif /* Don't USE_GAS */
979 : (flag_pic ? "bsr%. %0#plt" : "bsr%. %0"));
983 output_short_branch_defs (stream)
986 char name[256], high[256], low[256];
988 for (; sb_name && sb_high && sb_low;
989 sb_name = XEXP (sb_name, 1),
990 sb_high = XEXP (sb_high, 1),
991 sb_low = XEXP (sb_low, 1))
993 ASM_GENERATE_INTERNAL_LABEL
994 (name, "L", CODE_LABEL_NUMBER (XEXP (sb_name, 0)));
995 ASM_GENERATE_INTERNAL_LABEL
996 (high, "L", CODE_LABEL_NUMBER (XEXP (sb_high, 0)));
997 ASM_GENERATE_INTERNAL_LABEL
998 (low, "L", CODE_LABEL_NUMBER (XEXP (sb_low, 0)));
999 /* This will change as the assembler requirements become known. */
1000 fprintf (stream, "%s%s,%s-%s\n",
1001 SET_ASM_OP, &name[1], &high[1], &low[1]);
1003 if (sb_name || sb_high || sb_low)
1007 /* Return truth value of the statement that this conditional branch is likely
1008 to fall through. CONDITION, is the condition that JUMP_INSN is testing. */
1011 mostly_false_jump (jump_insn, condition)
1012 rtx jump_insn, condition;
1014 rtx target_label = JUMP_LABEL (jump_insn);
1017 /* Much of this isn't computed unless we're optimizing. */
1021 /* Determine if one path or the other leads to a return. */
1022 for (insnt = NEXT_INSN (target_label);
1024 insnt = NEXT_INSN (insnt))
1026 if (GET_CODE (insnt) == JUMP_INSN)
1028 else if (GET_CODE (insnt) == INSN
1029 && GET_CODE (PATTERN (insnt)) == SEQUENCE
1030 && GET_CODE (XVECEXP (PATTERN (insnt), 0, 0)) == JUMP_INSN)
1032 insnt = XVECEXP (PATTERN (insnt), 0, 0);
1037 && (GET_CODE (PATTERN (insnt)) == RETURN
1038 || (GET_CODE (PATTERN (insnt)) == SET
1039 && GET_CODE (SET_SRC (PATTERN (insnt))) == REG
1040 && REGNO (SET_SRC (PATTERN (insnt))) == 1)))
1043 for (insnj = NEXT_INSN (jump_insn);
1045 insnj = NEXT_INSN (insnj))
1047 if (GET_CODE (insnj) == JUMP_INSN)
1049 else if (GET_CODE (insnj) == INSN
1050 && GET_CODE (PATTERN (insnj)) == SEQUENCE
1051 && GET_CODE (XVECEXP (PATTERN (insnj), 0, 0)) == JUMP_INSN)
1053 insnj = XVECEXP (PATTERN (insnj), 0, 0);
1058 && (GET_CODE (PATTERN (insnj)) == RETURN
1059 || (GET_CODE (PATTERN (insnj)) == SET
1060 && GET_CODE (SET_SRC (PATTERN (insnj))) == REG
1061 && REGNO (SET_SRC (PATTERN (insnj))) == 1)))
1064 /* Predict to not return. */
1065 if ((insnt == 0) != (insnj == 0))
1066 return (insnt == 0);
1068 /* Predict loops to loop. */
1069 for (insnt = PREV_INSN (target_label);
1070 insnt && GET_CODE (insnt) == NOTE;
1071 insnt = PREV_INSN (insnt))
1072 if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_END)
1074 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_BEG)
1076 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_CONT)
1079 /* Predict backward branches usually take. */
1081 insnj = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
1084 if (INSN_ADDRESSES (INSN_UID (insnj))
1085 > INSN_ADDRESSES (INSN_UID (target_label)))
1088 /* EQ tests are usually false and NE tests are usually true. Also,
1089 most quantities are positive, so we can make the appropriate guesses
1090 about signed comparisons against zero. Consider unsigned comparisons
1091 to be a range check and assume quantities to be in range. */
1092 switch (GET_CODE (condition))
1095 /* Unconditional branch. */
1104 case GTU: /* Must get casesi right at least. */
1105 if (XEXP (condition, 1) == const0_rtx)
1112 if (XEXP (condition, 1) == const0_rtx)
1122 /* Return true if the operand is a power of two and is a floating
1123 point type (to optimize division by power of two into multiplication). */
1126 real_power_of_2_operand (op, mode)
1128 enum machine_mode mode ATTRIBUTE_UNUSED;
1133 struct { /* IEEE double precision format */
1135 unsigned exponent : 11;
1136 unsigned mantissa1 : 20;
1139 struct { /* IEEE double format to quick check */
1140 unsigned sign : 1; /* if it fits in a float */
1141 unsigned exponent1 : 4;
1142 unsigned exponent2 : 7;
1143 unsigned mantissa1 : 20;
1148 if (GET_MODE (op) != DFmode && GET_MODE (op) != SFmode)
1151 if (GET_CODE (op) != CONST_DOUBLE)
1154 REAL_VALUE_FROM_CONST_DOUBLE (d, op);
1155 REAL_VALUE_TO_TARGET_DOUBLE (d, u.l);
1157 if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0 /* not a power of two */
1158 || u.s.exponent == 0 /* constant 0.0 */
1159 || u.s.exponent == 0x7ff /* NAN */
1160 || (u.s2.exponent1 != 0x8 && u.s2.exponent1 != 0x7))
1161 return 0; /* const won't fit in float */
1166 /* Make OP legitimate for mode MODE. Currently this only deals with DFmode
1167 operands, putting them in registers and making CONST_DOUBLE values
1168 SFmode where possible. */
1171 legitimize_operand (op, mode)
1173 enum machine_mode mode;
1179 struct { /* IEEE double precision format */
1181 unsigned exponent : 11;
1182 unsigned mantissa1 : 20;
1185 struct { /* IEEE double format to quick check */
1186 unsigned sign : 1; /* if it fits in a float */
1187 unsigned exponent1 : 4;
1188 unsigned exponent2 : 7;
1189 unsigned mantissa1 : 20;
1194 if (GET_CODE (op) == REG || mode != DFmode)
1197 if (GET_CODE (op) == CONST_DOUBLE)
1199 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
1200 REAL_VALUE_TO_TARGET_DOUBLE (r, u.l);
1201 if (u.d.exponent != 0x7ff /* NaN */
1202 && u.d.mantissa2 == 0 /* Mantissa fits */
1203 && (u.s.exponent1 == 0x8 || u.s.exponent1 == 0x7) /* Exponent fits */
1204 && (temp = simplify_unary_operation (FLOAT_TRUNCATE, SFmode,
1206 return gen_rtx_FLOAT_EXTEND (mode, force_reg (SFmode, temp));
1208 else if (register_operand (op, mode))
1211 return force_reg (mode, op);
1214 /* Return true if OP is a suitable input for a move insn. */
1217 move_operand (op, mode)
1219 enum machine_mode mode;
1221 if (register_operand (op, mode))
1223 if (GET_CODE (op) == CONST_INT)
1224 return (classify_integer (mode, INTVAL (op)) < m88k_oru_hi16);
1225 if (GET_MODE (op) != mode)
1227 if (GET_CODE (op) == SUBREG)
1228 op = SUBREG_REG (op);
1229 if (GET_CODE (op) != MEM)
1233 if (GET_CODE (op) == LO_SUM)
1234 return (REG_P (XEXP (op, 0))
1235 && symbolic_address_p (XEXP (op, 1)));
1236 return memory_address_p (mode, op);
1239 /* Return true if OP is suitable for a call insn. */
1242 call_address_operand (op, mode)
1244 enum machine_mode mode ATTRIBUTE_UNUSED;
1246 return (REG_P (op) || symbolic_address_p (op));
1249 /* Returns true if OP is either a symbol reference or a sum of a symbol
1250 reference and a constant. */
1253 symbolic_address_p (op)
1256 switch (GET_CODE (op))
1264 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1265 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1266 && GET_CODE (XEXP (op, 1)) == CONST_INT);
1273 /* Return true if OP is a register or const0_rtx. */
1276 reg_or_0_operand (op, mode)
1278 enum machine_mode mode;
1280 return (op == const0_rtx || register_operand (op, mode));
1283 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
1286 arith_operand (op, mode)
1288 enum machine_mode mode;
1290 return (register_operand (op, mode)
1291 || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
1294 /* Return true if OP is a register or 5 bit integer. */
1297 arith5_operand (op, mode)
1299 enum machine_mode mode;
1301 return (register_operand (op, mode)
1302 || (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32));
1306 arith32_operand (op, mode)
1308 enum machine_mode mode;
1310 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
1314 arith64_operand (op, mode)
1316 enum machine_mode mode;
1318 return (register_operand (op, mode)
1319 || GET_CODE (op) == CONST_INT
1320 || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode));
1324 int5_operand (op, mode)
1326 enum machine_mode mode ATTRIBUTE_UNUSED;
1328 return (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32);
1332 int32_operand (op, mode)
1334 enum machine_mode mode ATTRIBUTE_UNUSED;
1336 return (GET_CODE (op) == CONST_INT);
1339 /* Return true if OP is a register or a valid immediate operand for
1343 add_operand (op, mode)
1345 enum machine_mode mode;
1347 return (register_operand (op, mode)
1348 || (GET_CODE (op) == CONST_INT && ADD_INT (op)));
1351 /* Nonzero if this is a bitmask filling the bottom bits, for optimizing and +
1352 shift left combinations into a single mak instruction. */
1358 return (value && POWER_OF_2_or_0 (value + 1));
1362 reg_or_bbx_mask_operand (op, mode)
1364 enum machine_mode mode;
1367 if (register_operand (op, mode))
1369 if (GET_CODE (op) != CONST_INT)
1372 value = INTVAL (op);
1373 if (POWER_OF_2 (value))
1379 /* Return true if OP is valid to use in the context of a floating
1380 point operation. Special case 0.0, since we can use r0. */
1383 real_or_0_operand (op, mode)
1385 enum machine_mode mode;
1387 if (mode != SFmode && mode != DFmode)
1390 return (register_operand (op, mode)
1391 || (GET_CODE (op) == CONST_DOUBLE
1392 && op == CONST0_RTX (mode)));
1395 /* Return true if OP is valid to use in the context of logic arithmetic
1396 on condition codes. */
1399 partial_ccmode_register_operand (op, mode)
1401 enum machine_mode mode ATTRIBUTE_UNUSED;
1403 return register_operand (op, CCmode) || register_operand (op, CCEVENmode);
1406 /* Return true if OP is a relational operator. */
1411 enum machine_mode mode ATTRIBUTE_UNUSED;
1413 switch (GET_CODE (op))
1432 even_relop (op, mode)
1434 enum machine_mode mode ATTRIBUTE_UNUSED;
1436 switch (GET_CODE (op))
1450 odd_relop (op, mode)
1452 enum machine_mode mode ATTRIBUTE_UNUSED;
1454 switch (GET_CODE (op))
1467 /* Return true if OP is a relational operator, and is not an unsigned
1468 relational operator. */
1471 relop_no_unsigned (op, mode)
1473 enum machine_mode mode ATTRIBUTE_UNUSED;
1475 switch (GET_CODE (op))
1483 /* @@ What is this test doing? Why not use `mode'? */
1484 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
1485 || GET_MODE (op) == DImode
1486 || GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_FLOAT
1487 || GET_MODE (XEXP (op, 0)) == DImode
1488 || GET_MODE_CLASS (GET_MODE (XEXP (op, 1))) == MODE_FLOAT
1489 || GET_MODE (XEXP (op, 1)) == DImode)
1497 /* Return true if the code of this rtx pattern is EQ or NE. */
1500 equality_op (op, mode)
1502 enum machine_mode mode ATTRIBUTE_UNUSED;
1504 return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
1507 /* Return true if the code of this rtx pattern is pc or label_ref. */
1510 pc_or_label_ref (op, mode)
1512 enum machine_mode mode ATTRIBUTE_UNUSED;
1514 return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF);
1517 /* Output to FILE the start of the assembler file. */
1519 /* This definition must match lang_independent_options from toplev.c. */
1520 struct m88k_lang_independent_options
1522 const char *const string;
1523 int *const variable;
1525 const char *const description;
1528 static void output_options PARAMS ((FILE *,
1529 const struct m88k_lang_independent_options *,
1531 const struct m88k_lang_independent_options *,
1532 int, int, int, const char *, const char *,
1536 output_option (file, sep, type, name, indent, pos, max)
1545 if ((long)(strlen (sep) + strlen (type) + strlen (name) + pos) > max)
1547 fprintf (file, indent);
1548 return fprintf (file, "%s%s", type, name);
1550 return pos + fprintf (file, "%s%s%s", sep, type, name);
1553 static const struct { const char *const name; const int value; } m_options[] =
1557 output_options (file, f_options, f_len, W_options, W_len,
1558 pos, max, sep, indent, term)
1560 const struct m88k_lang_independent_options *f_options;
1561 const struct m88k_lang_independent_options *W_options;
1572 pos = output_option (file, sep, "-O", "", indent, pos, max);
1573 if (write_symbols != NO_DEBUG)
1574 pos = output_option (file, sep, "-g", "", indent, pos, max);
1576 pos = output_option (file, sep, "-p", "", indent, pos, max);
1577 for (j = 0; j < f_len; j++)
1578 if (*f_options[j].variable == f_options[j].on_value)
1579 pos = output_option (file, sep, "-f", f_options[j].string,
1582 for (j = 0; j < W_len; j++)
1583 if (*W_options[j].variable == W_options[j].on_value)
1584 pos = output_option (file, sep, "-W", W_options[j].string,
1587 for (j = 0; j < (long) ARRAY_SIZE (m_options); j++)
1588 if (m_options[j].name[0] != '\0'
1589 && m_options[j].value > 0
1590 && ((m_options[j].value & target_flags)
1591 == m_options[j].value))
1592 pos = output_option (file, sep, "-m", m_options[j].name,
1595 if (m88k_short_data)
1596 pos = output_option (file, sep, "-mshort-data-", m88k_short_data,
1599 fprintf (file, term);
1603 output_file_start (file, f_options, f_len, W_options, W_len)
1605 const struct m88k_lang_independent_options *f_options;
1606 const struct m88k_lang_independent_options *W_options;
1611 ASM_FIRST_LINE (file);
1614 fprintf (file, "%s\n", REQUIRES_88110_ASM_OP);
1615 output_file_directive (file, main_input_filename);
1616 /* Switch to the data section so that the coffsem symbol
1617 isn't in the text section. */
1620 if (TARGET_IDENTIFY_REVISION)
1624 time_t now = time ((time_t *)0);
1625 sprintf (indent, "]\"\n%s\"@(#)%s [", IDENT_ASM_OP, main_input_filename);
1626 fprintf (file, indent+3);
1627 pos = fprintf (file, "gcc %s, %.24s,", version_string, ctime (&now));
1629 /* ??? It would be nice to call print_switch_values here (and thereby
1630 let us delete output_options) but this is kept in until it is known
1631 whether the change in content format matters. */
1632 output_options (file, f_options, f_len, W_options, W_len,
1633 pos, 150 - strlen (indent), " ", indent, "]\"\n\n");
1635 fprintf (file, "]\"\n");
1636 print_switch_values (file, 0, 150 - strlen (indent),
1637 indent + 3, " ", "]\"\n");
1642 /* Output an ascii string. */
1645 output_ascii (file, opcode, max, p, size)
1655 register int num = 0;
1657 fprintf (file, "%s\"", opcode);
1658 for (i = 0; i < size; i++)
1660 register int c = (unsigned char) p[i];
1664 fprintf (file, "\"\n%s\"", opcode);
1668 if (c == '\"' || c == '\\')
1676 else if (in_escape && ISDIGIT (c))
1678 /* If a digit follows an octal-escape, the VAX assembler fails
1679 to stop reading the escape after three digits. Continue to
1680 output the values as an octal-escape until a non-digit is
1682 fprintf (file, "\\%03o", c);
1685 else if ((c >= ' ' && c < 0177) || (c == '\t'))
1695 /* Some assemblers can't handle \a, \v, or \?. */
1696 case '\f': c = 'f'; goto escape;
1697 case '\b': c = 'b'; goto escape;
1698 case '\r': c = 'r'; goto escape;
1699 case '\n': c = 'n'; goto escape;
1702 fprintf (file, "\\%03o", c);
1707 fprintf (file, "\"\n");
1710 /* Output a label (allows insn-output.c to be compiled without including
1711 m88k.c or needing to include stdio.h). */
1714 output_label (label_number)
1717 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", label_number);
1720 /* Generate the assembly code for function entry.
1722 The prologue is responsible for setting up the stack frame,
1723 initializing the frame pointer register, saving registers that must be
1724 saved, and allocating SIZE additional bytes of storage for the
1725 local variables. SIZE is an integer. FILE is a stdio
1726 stream to which the assembler code should be output.
1728 The label for the beginning of the function need not be output by this
1729 macro. That has already been done when the macro is run.
1731 To determine which registers to save, the macro can refer to the array
1732 `regs_ever_live': element R is nonzero if hard register
1733 R is used anywhere within the function. This implies the
1734 function prologue should save register R, but not if it is one
1735 of the call-used registers.
1737 On machines where functions may or may not have frame-pointers, the
1738 function entry code must vary accordingly; it must set up the frame
1739 pointer if one is wanted, and not otherwise. To determine whether a
1740 frame pointer is in wanted, the macro can refer to the variable
1741 `frame_pointer_needed'. The variable's value will be 1 at run
1742 time in a function that needs a frame pointer.
1744 On machines where an argument may be passed partly in registers and
1745 partly in memory, this macro must examine the variable
1746 `current_function_pretend_args_size', and allocate that many bytes
1747 of uninitialized space on the stack just underneath the first argument
1748 arriving on the stack. (This may not be at the very end of the stack,
1749 if the calling sequence has pushed anything else since pushing the stack
1750 arguments. But usually, on such machines, nothing else has been pushed
1751 yet, because the function prologue itself does all the pushing.)
1753 If `ACCUMULATE_OUTGOING_ARGS' is defined, the variable
1754 `current_function_outgoing_args_size' contains the size in bytes
1755 required for the outgoing arguments. This macro must add that
1756 amount of uninitialized space to very bottom of the stack.
1758 The stack frame we use looks like this:
1761 |==============================================|
1763 |==============================================|
1764 | [caller's outgoing memory arguments] |
1765 |==============================================|
1766 | caller's outgoing argument area (32 bytes) |
1767 sp -> |==============================================| <- ap
1768 | [local variable space] |
1769 |----------------------------------------------|
1770 | [return address (r1)] |
1771 |----------------------------------------------|
1772 | [previous frame pointer (r30)] |
1773 |==============================================| <- fp
1774 | [preserved registers (r25..r14)] |
1775 |----------------------------------------------|
1776 | [preserved registers (x29..x22)] |
1777 |==============================================|
1778 | [dynamically allocated space (alloca)] |
1779 |==============================================|
1780 | [callee's outgoing memory arguments] |
1781 |==============================================|
1782 | [callee's outgoing argument area (32 bytes)] |
1783 |==============================================| <- sp
1787 r1 and r30 must be saved if debugging.
1789 fp (if present) is located two words down from the local
1793 static void emit_add PARAMS ((rtx, rtx, int));
1794 static void preserve_registers PARAMS ((int, int));
1795 static void emit_ldst PARAMS ((int, int, enum machine_mode, int));
1796 static void output_tdesc PARAMS ((FILE *, int));
1797 static int uses_arg_area_p PARAMS ((void));
1801 static char save_regs[FIRST_PSEUDO_REGISTER];
1802 static int frame_laid_out;
1803 static int frame_size;
1804 static int variable_args_p;
1805 static int epilogue_marked;
1806 static int prologue_marked;
1808 #define FIRST_OCS_PRESERVE_REGISTER 14
1809 #define LAST_OCS_PRESERVE_REGISTER 30
1811 #define FIRST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 22)
1812 #define LAST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 31)
1814 #define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
1815 #define ROUND_CALL_BLOCK_SIZE(BYTES) \
1816 (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
1818 /* Establish the position of the FP relative to the SP. This is done
1819 either during output_function_prologue() or by
1820 INITIAL_ELIMINATION_OFFSET. */
1823 m88k_layout_frame ()
1829 memset ((char *) &save_regs[0], 0, sizeof (save_regs));
1830 sp_size = nregs = nxregs = 0;
1831 frame_size = get_frame_size ();
1833 /* Since profiling requires a call, make sure r1 is saved. */
1834 if (current_function_profile)
1837 /* If we are producing debug information, store r1 and r30 where the
1838 debugger wants to find them (r30 at r30+0, r1 at r30+4). Space has
1839 already been reserved for r1/r30 in STARTING_FRAME_OFFSET. */
1840 if (write_symbols != NO_DEBUG && !TARGET_OCS_FRAME_POSITION)
1843 /* If there is a call, alloca is used, __builtin_alloca is used, or
1844 a dynamic-sized object is defined, add the 8 additional words
1845 for the callee's argument area. The common denominator is that the
1846 FP is required. may_call_alloca only gets calls to alloca;
1847 current_function_calls_alloca gets alloca and __builtin_alloca. */
1848 if (regs_ever_live[1] || frame_pointer_needed)
1851 sp_size += REG_PARM_STACK_SPACE (0);
1854 /* If we are producing PIC, save the addressing base register and r1. */
1855 if (flag_pic && current_function_uses_pic_offset_table)
1857 save_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
1861 /* If a frame is requested, save the previous FP, and the return
1862 address (r1), so that a traceback can be done without using tdesc
1863 information. Otherwise, simply save the FP if it is used as
1864 a preserve register. */
1865 if (frame_pointer_needed)
1866 save_regs[FRAME_POINTER_REGNUM] = save_regs[1] = 1;
1867 else if (regs_ever_live[FRAME_POINTER_REGNUM])
1868 save_regs[FRAME_POINTER_REGNUM] = 1;
1870 /* Figure out which extended register(s) needs to be saved. */
1871 for (regno = FIRST_EXTENDED_REGISTER + 1; regno < FIRST_PSEUDO_REGISTER;
1873 if (regs_ever_live[regno] && ! call_used_regs[regno])
1875 save_regs[regno] = 1;
1879 /* Figure out which normal register(s) needs to be saved. */
1880 for (regno = 2; regno < FRAME_POINTER_REGNUM; regno++)
1881 if (regs_ever_live[regno] && ! call_used_regs[regno])
1883 save_regs[regno] = 1;
1887 /* Achieve greatest use of double memory ops. Either we end up saving
1888 r30 or we use that slot to align the registers we do save. */
1889 if (nregs >= 2 && save_regs[1] && !save_regs[FRAME_POINTER_REGNUM])
1892 nregs += save_regs[1] + save_regs[FRAME_POINTER_REGNUM];
1893 /* if we need to align extended registers, add a word */
1894 if (nxregs > 0 && (nregs & 1) != 0)
1896 sp_size += 4 * nregs;
1897 sp_size += 8 * nxregs;
1898 sp_size += current_function_outgoing_args_size;
1900 /* The first two saved registers are placed above the new frame pointer
1901 if any. In the only case this matters, they are r1 and r30. */
1902 if (frame_pointer_needed || sp_size)
1903 m88k_fp_offset = ROUND_CALL_BLOCK_SIZE (sp_size - STARTING_FRAME_OFFSET);
1905 m88k_fp_offset = -STARTING_FRAME_OFFSET;
1906 m88k_stack_size = m88k_fp_offset + STARTING_FRAME_OFFSET;
1908 /* First, combine m88k_stack_size and size. If m88k_stack_size is
1909 nonzero, align the frame size to 8 mod 16; otherwise align the
1910 frame size to 0 mod 16. (If stacks are 8 byte aligned, this ends
1914 = ((m88k_stack_size ? STACK_UNIT_BOUNDARY - STARTING_FRAME_OFFSET : 0)
1915 - (frame_size % STACK_UNIT_BOUNDARY));
1917 need += STACK_UNIT_BOUNDARY;
1919 = ROUND_CALL_BLOCK_SIZE (m88k_stack_size + frame_size + need
1920 + current_function_pretend_args_size);
1924 /* Return true if this function is known to have a null prologue. */
1929 if (! reload_completed)
1931 if (! frame_laid_out)
1932 m88k_layout_frame ();
1933 return (! frame_pointer_needed
1936 && m88k_stack_size == 0);
1939 /* Determine if the current function has any references to the arg pointer.
1940 This is done indirectly by examining the DECL_ARGUMENTS' DECL_RTL.
1941 It is OK to return TRUE if there are no references, but FALSE must be
1949 if (current_function_decl == 0
1953 for (parm = DECL_ARGUMENTS (current_function_decl);
1955 parm = TREE_CHAIN (parm))
1957 if (DECL_RTL (parm) == 0
1958 || GET_CODE (DECL_RTL (parm)) == MEM)
1961 if (DECL_INCOMING_RTL (parm) == 0
1962 || GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
1969 m88k_output_function_prologue (stream, size)
1970 FILE *stream ATTRIBUTE_UNUSED;
1971 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
1973 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! quiet_flag && leaf_function_p ())
1974 fprintf (stderr, "$");
1976 m88k_prologue_done = 1; /* it's ok now to put out ln directives */
1980 m88k_output_function_end_prologue (stream)
1983 if (TARGET_OCS_DEBUG_INFO && !prologue_marked)
1985 PUT_OCS_FUNCTION_START (stream);
1986 prologue_marked = 1;
1988 /* If we've already passed the start of the epilogue, say that
1989 it starts here. This marks the function as having a null body,
1990 but at a point where the return address is in a known location.
1992 Originally, I thought this couldn't happen, but the pic prologue
1993 for leaf functions ends with the instruction that restores the
1994 return address from the temporary register. If the temporary
1995 register is never used, that instruction can float all the way
1996 to the end of the function. */
1997 if (epilogue_marked)
1998 PUT_OCS_FUNCTION_END (stream);
2003 m88k_expand_prologue ()
2005 m88k_layout_frame ();
2007 if (TARGET_OPTIMIZE_ARG_AREA
2009 && ! uses_arg_area_p ())
2011 /* The incoming argument area is used for stack space if it is not
2012 used (or if -mno-optimize-arg-area is given). */
2013 if ((m88k_stack_size -= REG_PARM_STACK_SPACE (0)) < 0)
2014 m88k_stack_size = 0;
2017 if (m88k_stack_size)
2018 emit_add (stack_pointer_rtx, stack_pointer_rtx, -m88k_stack_size);
2020 if (nregs || nxregs)
2021 preserve_registers (m88k_fp_offset + 4, 1);
2023 if (frame_pointer_needed)
2024 emit_add (frame_pointer_rtx, stack_pointer_rtx, m88k_fp_offset);
2026 if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM])
2028 rtx return_reg = gen_rtx_REG (SImode, 1);
2029 rtx label = gen_label_rtx ();
2030 rtx temp_reg = NULL_RTX;
2034 temp_reg = gen_rtx_REG (SImode, TEMP_REGNUM);
2035 emit_move_insn (temp_reg, return_reg);
2037 emit_insn (gen_locate1 (pic_offset_table_rtx, label));
2038 emit_insn (gen_locate2 (pic_offset_table_rtx, label));
2039 emit_insn (gen_addsi3 (pic_offset_table_rtx,
2040 pic_offset_table_rtx, return_reg));
2042 emit_move_insn (return_reg, temp_reg);
2044 if (current_function_profile)
2045 emit_insn (gen_blockage ());
2048 /* This function generates the assembly code for function exit,
2049 on machines that need it.
2051 The function epilogue should not depend on the current stack pointer!
2052 It should use the frame pointer only, if there is a frame pointer.
2053 This is mandatory because of alloca; we also take advantage of it to
2054 omit stack adjustments before returning. */
2057 m88k_output_function_begin_epilogue (stream)
2060 if (TARGET_OCS_DEBUG_INFO && !epilogue_marked && prologue_marked)
2062 PUT_OCS_FUNCTION_END (stream);
2064 epilogue_marked = 1;
2068 m88k_output_function_epilogue (stream, size)
2070 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
2072 rtx insn = get_last_insn ();
2074 if (TARGET_OCS_DEBUG_INFO && !epilogue_marked)
2075 PUT_OCS_FUNCTION_END (stream);
2077 /* If the last insn isn't a BARRIER, we must write a return insn. This
2078 should only happen if the function has no prologue and no body. */
2079 if (GET_CODE (insn) == NOTE)
2080 insn = prev_nonnote_insn (insn);
2081 if (insn == 0 || GET_CODE (insn) != BARRIER)
2082 fprintf (stream, "\tjmp\t %s\n", reg_names[1]);
2084 /* If the last insn is a barrier, and the insn before that is a call,
2085 then add a nop instruction so that tdesc can walk the stack correctly
2086 even though there is no epilogue. (Otherwise, the label for the
2087 end of the tdesc region ends up at the start of the next function. */
2088 if (insn && GET_CODE (insn) == BARRIER)
2090 insn = prev_nonnote_insn (insn);
2091 if (insn && GET_CODE (insn) == CALL_INSN)
2092 fprintf (stream, "\tor\t %s,%s,%s\n",reg_names[0],reg_names[0],reg_names[0]);
2095 output_short_branch_defs (stream);
2097 fprintf (stream, "\n");
2099 if (TARGET_OCS_DEBUG_INFO)
2100 output_tdesc (stream, m88k_fp_offset + 4);
2102 m88k_function_number++;
2103 m88k_prologue_done = 0; /* don't put out ln directives */
2104 variable_args_p = 0; /* has variable args */
2106 epilogue_marked = 0;
2107 prologue_marked = 0;
2111 m88k_expand_epilogue ()
2113 #if (MONITOR_GCC & 0x4) /* What are interesting prologue/epilogue values? */
2114 fprintf (stream, "; size = %d, m88k_fp_offset = %d, m88k_stack_size = %d\n",
2115 size, m88k_fp_offset, m88k_stack_size);
2118 if (frame_pointer_needed)
2119 emit_add (stack_pointer_rtx, frame_pointer_rtx, -m88k_fp_offset);
2121 if (nregs || nxregs)
2122 preserve_registers (m88k_fp_offset + 4, 0);
2124 if (m88k_stack_size)
2125 emit_add (stack_pointer_rtx, stack_pointer_rtx, m88k_stack_size);
2128 /* Emit insns to set DSTREG to SRCREG + AMOUNT during the prologue or
2132 emit_add (dstreg, srcreg, amount)
2137 rtx incr = GEN_INT (abs (amount));
2139 if (! ADD_INTVAL (amount))
2141 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
2142 emit_move_insn (temp, incr);
2145 emit_insn ((amount < 0 ? gen_subsi3 : gen_addsi3) (dstreg, srcreg, incr));
2148 /* Save/restore the preserve registers. base is the highest offset from
2149 r31 at which a register is stored. store_p is true if stores are to
2150 be done; otherwise loads. */
2153 preserve_registers (base, store_p)
2162 } mem_op[FIRST_PSEUDO_REGISTER];
2163 struct mem_op *mo_ptr = mem_op;
2165 /* The 88open OCS mandates that preserved registers be stored in
2166 increasing order. For compatibility with current practice,
2167 the order is r1, r30, then the preserve registers. */
2172 /* An extra word is given in this case to make best use of double
2174 if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM])
2176 emit_ldst (store_p, 1, SImode, offset);
2181 /* Walk the registers to save recording all single memory operations. */
2182 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2183 if (save_regs[regno])
2185 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2188 mo_ptr->regno = regno;
2189 mo_ptr->offset = offset;
2200 /* Walk the registers to save recording all double memory operations.
2201 This avoids a delay in the epilogue (ld.d/ld). */
2203 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2204 if (save_regs[regno])
2206 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2213 mo_ptr->regno = regno-1;
2214 mo_ptr->offset = offset-4;
2221 /* Walk the extended registers to record all memory operations. */
2222 /* Be sure the offset is double word aligned. */
2223 offset = (offset - 1) & ~7;
2224 for (regno = FIRST_PSEUDO_REGISTER - 1; regno > FIRST_EXTENDED_REGISTER;
2226 if (save_regs[regno])
2229 mo_ptr->regno = regno;
2230 mo_ptr->offset = offset;
2237 /* Output the memory operations. */
2238 for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++)
2241 emit_ldst (store_p, mo_ptr->regno,
2242 (mo_ptr->nregs > 1 ? DImode : SImode),
2248 emit_ldst (store_p, regno, mode, offset)
2251 enum machine_mode mode;
2254 rtx reg = gen_rtx_REG (mode, regno);
2257 if (SMALL_INTVAL (offset))
2259 mem = gen_rtx_MEM (mode, plus_constant (stack_pointer_rtx, offset));
2263 /* offset is too large for immediate index must use register */
2265 rtx disp = GEN_INT (offset);
2266 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
2267 rtx regi = gen_rtx_PLUS (SImode, stack_pointer_rtx, temp);
2269 emit_move_insn (temp, disp);
2270 mem = gen_rtx_MEM (mode, regi);
2274 emit_move_insn (mem, reg);
2276 emit_move_insn (reg, mem);
2279 /* Convert the address expression REG to a CFA offset. */
2282 m88k_debugger_offset (reg, offset)
2284 register int offset;
2286 if (GET_CODE (reg) == PLUS)
2288 offset = INTVAL (XEXP (reg, 1));
2289 reg = XEXP (reg, 0);
2292 /* Put the offset in terms of the CFA (arg pointer). */
2293 if (reg == frame_pointer_rtx)
2294 offset += m88k_fp_offset - m88k_stack_size;
2295 else if (reg == stack_pointer_rtx)
2296 offset -= m88k_stack_size;
2297 else if (reg != arg_pointer_rtx)
2299 #if (MONITOR_GCC & 0x10) /* Watch for suspicious symbolic locations. */
2300 if (! (GET_CODE (reg) == REG
2301 && REGNO (reg) >= FIRST_PSEUDO_REGISTER))
2302 warning ("internal gcc error: Can't express symbolic location");
2310 /* Output the 88open OCS proscribed text description information.
2313 0 22: info-byte-length (16 or 20 bytes)
2314 0 2: info-alignment (word 2)
2315 1 32: info-protocol (version 1 or 2(pic))
2316 2 32: starting-address (inclusive, not counting prologue)
2317 3 32: ending-address (exclusive, not counting epilog)
2318 4 8: info-variant (version 1 or 3(extended registers))
2319 4 17: register-save-mask (from register 14 to 30)
2321 4 1: return-address-info-discriminant
2322 4 5: frame-address-register
2323 5 32: frame-address-offset
2324 6 32: return-address-info
2325 7 32: register-save-offset
2326 8 16: extended-register-save-mask (x16 - x31)
2327 8 16: extended-register-save-offset (WORDS from register-save-offset) */
2330 output_tdesc (file, offset)
2335 long mask, return_address_info, register_save_offset;
2336 long xmask, xregister_save_offset;
2339 for (mask = 0, i = 0, regno = FIRST_OCS_PRESERVE_REGISTER;
2340 regno <= LAST_OCS_PRESERVE_REGISTER;
2344 if (save_regs[regno])
2351 for (xmask = 0, j = 0, regno = FIRST_OCS_EXTENDED_PRESERVE_REGISTER;
2352 regno <= LAST_OCS_EXTENDED_PRESERVE_REGISTER;
2356 if (save_regs[regno])
2365 if ((nxregs > 0 || nregs > 2) && !save_regs[FRAME_POINTER_REGNUM])
2367 return_address_info = - m88k_stack_size + offset;
2368 register_save_offset = return_address_info - i*4;
2372 return_address_info = 1;
2373 register_save_offset = - m88k_stack_size + offset + 4 - i*4;
2376 xregister_save_offset = - (j * 2 + ((register_save_offset >> 2) & 1));
2380 /* 8:0,22:(20 or 16),2:2 */
2381 fprintf (file, "%s%d,%d", integer_asm_op (4, TRUE),
2382 (((xmask != 0) ? 20 : 16) << 2) | 2,
2385 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_START_PREFIX, m88k_function_number);
2386 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2387 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_END_PREFIX, m88k_function_number);
2388 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2390 fprintf (file, ",0x%x,0x%x,0x%lx,0x%lx",
2391 /* 8:1,17:0x%.3x,1:0,1:%d,5:%d */
2392 (int)(((xmask ? 3 : 1) << (17+1+1+5))
2394 | ((!!save_regs[1]) << 5)
2395 | (frame_pointer_needed
2396 ? FRAME_POINTER_REGNUM
2397 : STACK_POINTER_REGNUM)),
2398 (m88k_stack_size - (frame_pointer_needed ? m88k_fp_offset : 0)),
2399 return_address_info,
2400 register_save_offset);
2402 fprintf (file, ",0x%lx%04lx", xmask, (0xffff & xregister_save_offset));
2408 /* Output assembler code to FILE to increment profiler label # LABELNO
2409 for profiling a function entry. NAME is the mcount function name
2410 (varies), SAVEP indicates whether the parameter registers need to
2411 be saved and restored. */
2414 output_function_profiler (file, labelno, name, savep)
2422 const char *const temp = (savep ? reg_names[2] : reg_names[10]);
2424 /* Remember to update FUNCTION_PROFILER_LENGTH. */
2428 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2429 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2430 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2431 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2432 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2435 ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno);
2438 fprintf (file, "\tor.u\t %s,%s,%shi16(%s#got_rel)\n",
2439 temp, reg_names[0], m88k_pound_sign, &label[1]);
2440 fprintf (file, "\tor\t %s,%s,%slo16(%s#got_rel)\n",
2441 temp, temp, m88k_pound_sign, &label[1]);
2442 sprintf (dbi, "\tld\t %s,%s,%s\n", temp,
2443 reg_names[PIC_OFFSET_TABLE_REGNUM], temp);
2447 sprintf (dbi, "\tld\t %s,%s,%s#got_rel\n", temp,
2448 reg_names[PIC_OFFSET_TABLE_REGNUM], &label[1]);
2452 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n",
2453 temp, reg_names[0], m88k_pound_sign, &label[1]);
2454 sprintf (dbi, "\tor\t %s,%s,%slo16(%s)\n",
2455 temp, temp, m88k_pound_sign, &label[1]);
2459 fprintf (file, "\tbsr.n\t %s#plt\n", name);
2461 fprintf (file, "\tbsr.n\t %s\n", name);
2466 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2467 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2468 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2469 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2470 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2474 /* Determine whether a function argument is passed in a register, and
2477 The arguments are CUM, which summarizes all the previous
2478 arguments; MODE, the machine mode of the argument; TYPE,
2479 the data type of the argument as a tree node or 0 if that is not known
2480 (which happens for C support library functions); and NAMED,
2481 which is 1 for an ordinary argument and 0 for nameless arguments that
2482 correspond to `...' in the called function's prototype.
2484 The value of the expression should either be a `reg' RTX for the
2485 hard register in which to pass the argument, or zero to pass the
2486 argument on the stack.
2488 On the m88000 the first eight words of args are normally in registers
2489 and the rest are pushed. Double precision floating point must be
2490 double word aligned (and if in a register, starting on an even
2491 register). Structures and unions which are not 4 byte, and word
2492 aligned are passed in memory rather than registers, even if they
2493 would fit completely in the registers under OCS rules.
2495 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2496 For structures that are passed in memory, but could have been
2497 passed in registers, we first load the structure into the
2498 register, and then when the last argument is passed, we store
2499 the registers into the stack locations. This fixes some bugs
2500 where GCC did not expect to have register arguments, followed
2501 by stack arguments, followed by register arguments. */
2504 m88k_function_arg (args_so_far, mode, type, named)
2505 CUMULATIVE_ARGS args_so_far;
2506 enum machine_mode mode;
2508 int named ATTRIBUTE_UNUSED;
2512 if (type != 0 /* undo putting struct in register */
2513 && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
2516 if (mode == BLKmode && TARGET_WARN_PASS_STRUCT)
2517 warning ("argument #%d is a structure", args_so_far + 1);
2519 if ((args_so_far & 1) != 0
2520 && (mode == DImode || mode == DFmode
2521 || (type != 0 && TYPE_ALIGN (type) > 32)))
2526 return (rtx) 0; /* don't put args in registers */
2529 if (type == 0 && mode == BLKmode)
2530 abort (); /* m88k_function_arg argument `type' is NULL for BLKmode. */
2532 bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
2533 words = (bytes + 3) / 4;
2535 if (args_so_far + words > 8)
2536 return (rtx) 0; /* args have exhausted registers */
2538 else if (mode == BLKmode
2539 && (TYPE_ALIGN (type) != BITS_PER_WORD
2540 || bytes != UNITS_PER_WORD))
2543 return gen_rtx_REG (((mode == BLKmode) ? TYPE_MODE (type) : mode),
2547 /* Do what is necessary for `va_start'. We look at the current function
2548 to determine if stdargs or varargs is used and spill as necessary.
2549 We return a pointer to the spill area. */
2552 m88k_builtin_saveregs ()
2555 tree fntype = TREE_TYPE (current_function_decl);
2556 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2557 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2558 != void_type_node)))
2559 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
2562 variable_args_p = 1;
2565 if (GET_CODE (current_function_arg_offset_rtx) == CONST_INT)
2566 fixed = ((INTVAL (current_function_arg_offset_rtx) + argadj)
2569 /* Allocate the register space, and store it as the __va_reg member. */
2570 addr = assign_stack_local (BLKmode, 8 * UNITS_PER_WORD, -1);
2571 set_mem_alias_set (addr, get_varargs_alias_set ());
2572 RTX_UNCHANGING_P (addr) = 1;
2573 RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
2575 /* Now store the incoming registers. */
2577 move_block_from_reg (2 + fixed,
2578 adjust_address (addr, Pmode, fixed * UNITS_PER_WORD),
2580 UNITS_PER_WORD * (8 - fixed));
2582 /* Return the address of the save area, but don't put it in a
2583 register. This fails when not optimizing and produces worse code
2585 return XEXP (addr, 0);
2588 /* Define the `__builtin_va_list' type for the ABI. */
2591 m88k_build_va_list ()
2593 tree field_reg, field_stk, field_arg, int_ptr_type_node, record;
2595 int_ptr_type_node = build_pointer_type (integer_type_node);
2597 record = make_node (RECORD_TYPE);
2599 field_arg = build_decl (FIELD_DECL, get_identifier ("__va_arg"),
2601 field_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"),
2603 field_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),
2606 DECL_FIELD_CONTEXT (field_arg) = record;
2607 DECL_FIELD_CONTEXT (field_stk) = record;
2608 DECL_FIELD_CONTEXT (field_reg) = record;
2610 TYPE_FIELDS (record) = field_arg;
2611 TREE_CHAIN (field_arg) = field_stk;
2612 TREE_CHAIN (field_stk) = field_reg;
2614 layout_type (record);
2618 /* Implement `va_start' for varargs and stdarg. */
2621 m88k_va_start (valist, nextarg)
2623 rtx nextarg ATTRIBUTE_UNUSED;
2625 tree field_reg, field_stk, field_arg;
2626 tree reg, stk, arg, t;
2628 field_arg = TYPE_FIELDS (va_list_type_node);
2629 field_stk = TREE_CHAIN (field_arg);
2630 field_reg = TREE_CHAIN (field_stk);
2632 arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
2633 stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
2634 reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
2636 /* Fill in the ARG member. */
2638 tree fntype = TREE_TYPE (current_function_decl);
2639 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2640 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2641 != void_type_node)))
2642 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
2645 if (CONSTANT_P (current_function_arg_offset_rtx))
2647 int fixed = (INTVAL (current_function_arg_offset_rtx)
2648 + argadj) / UNITS_PER_WORD;
2650 argsize = build_int_2 (fixed, 0);
2654 argsize = make_tree (integer_type_node,
2655 current_function_arg_offset_rtx);
2656 argsize = fold (build (PLUS_EXPR, integer_type_node, argsize,
2657 build_int_2 (argadj, 0)));
2658 argsize = fold (build (RSHIFT_EXPR, integer_type_node, argsize,
2659 build_int_2 (2, 0)));
2662 t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, argsize);
2663 TREE_SIDE_EFFECTS (t) = 1;
2664 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2667 /* Store the arg pointer in the __va_stk member. */
2668 t = make_tree (TREE_TYPE (stk), virtual_incoming_args_rtx);
2669 t = build (MODIFY_EXPR, TREE_TYPE (stk), stk, t);
2670 TREE_SIDE_EFFECTS (t) = 1;
2671 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2673 /* Tuck the return value from __builtin_saveregs into __va_reg. */
2674 t = make_tree (TREE_TYPE (reg), expand_builtin_saveregs ());
2675 t = build (MODIFY_EXPR, TREE_TYPE (reg), reg, t);
2676 TREE_SIDE_EFFECTS (t) = 1;
2677 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2680 /* Implement `va_arg'. */
2683 m88k_va_arg (valist, type)
2686 tree field_reg, field_stk, field_arg;
2687 tree reg, stk, arg, arg_align, base, t;
2688 int size, wsize, align, reg_p;
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 size = int_size_in_bytes (type);
2700 wsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
2701 align = 1 << ((TYPE_ALIGN (type) / BITS_PER_UNIT) >> 3);
2702 reg_p = (AGGREGATE_TYPE_P (type)
2703 ? size == UNITS_PER_WORD && TYPE_ALIGN (type) == BITS_PER_WORD
2704 : size <= 2*UNITS_PER_WORD);
2706 /* Align __va_arg to the (doubleword?) boundary above. */
2707 t = build (PLUS_EXPR, TREE_TYPE (arg), arg, build_int_2 (align - 1, 0));
2708 arg_align = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
2709 arg_align = save_expr (arg_align);
2711 /* Decide if we should read from stack or regs. */
2712 t = build (LT_EXPR, integer_type_node, arg_align, build_int_2 (8, 0));
2713 base = build (COND_EXPR, TREE_TYPE (reg), t, reg, stk);
2715 /* Find the final address. */
2716 t = build (PLUS_EXPR, TREE_TYPE (base), base, arg_align);
2717 addr_rtx = expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
2718 addr_rtx = copy_to_reg (addr_rtx);
2720 /* Increment __va_arg. */
2721 t = build (PLUS_EXPR, TREE_TYPE (arg), arg_align, build_int_2 (wsize, 0));
2722 t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, t);
2723 TREE_SIDE_EFFECTS (t) = 1;
2724 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2729 /* If cmpsi has not been generated, emit code to do the test. Return the
2730 expression describing the test of operator OP. */
2733 emit_test (op, mode)
2735 enum machine_mode mode;
2737 if (m88k_compare_reg == 0)
2738 emit_insn (gen_test (m88k_compare_op0, m88k_compare_op1));
2739 return (gen_rtx (op, mode, m88k_compare_reg, const0_rtx));
2742 /* Determine how to best perform cmpsi/bxx, where cmpsi has a constant
2743 operand. All tests with zero (albeit swapped) and all equality tests
2744 with a constant are done with bcnd. The remaining cases are swapped
2748 emit_bcnd (op, label)
2752 if (m88k_compare_op1 == const0_rtx)
2753 emit_jump_insn (gen_bcnd
2754 (gen_rtx (op, VOIDmode,m88k_compare_op0, const0_rtx),
2756 else if (m88k_compare_op0 == const0_rtx)
2757 emit_jump_insn (gen_bcnd
2758 (gen_rtx (swap_condition (op),
2759 VOIDmode, m88k_compare_op1, const0_rtx),
2761 else if (op != EQ && op != NE)
2762 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2765 rtx zero = gen_reg_rtx (SImode);
2769 if (GET_CODE (m88k_compare_op1) == CONST_INT)
2771 reg = force_reg (SImode, m88k_compare_op0);
2772 constant = m88k_compare_op1;
2776 reg = force_reg (SImode, m88k_compare_op1);
2777 constant = m88k_compare_op0;
2779 value = INTVAL (constant);
2781 /* Perform an arithmetic computation to make the compared-to value
2782 zero, but avoid loosing if the bcnd is later changed into sxx. */
2783 if (SMALL_INTVAL (value))
2784 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2787 if (SMALL_INTVAL (-value))
2788 emit_insn (gen_addsi3 (zero, reg,
2791 emit_insn (gen_xorsi3 (zero, reg, constant));
2793 emit_jump_insn (gen_bcnd (gen_rtx (op, VOIDmode,
2800 /* Print an operand. Recognize special options, documented below. */
2803 print_operand (file, x, code)
2808 enum rtx_code xc = (x ? GET_CODE (x) : UNKNOWN);
2809 register int value = (xc == CONST_INT ? INTVAL (x) : 0);
2810 static int sequencep;
2811 static int reversep;
2815 if (code < 'B' || code > 'E')
2816 output_operand_lossage ("%%R not followed by %%B/C/D/E");
2818 xc = reverse_condition (xc);
2824 case '*': /* addressing base register for PIC */
2825 fputs (reg_names[PIC_OFFSET_TABLE_REGNUM], file); return;
2827 case '#': /* SVR4 pound-sign syntax character (empty if SVR3) */
2828 fputs (m88k_pound_sign, file); return;
2830 case 'V': /* Output a serializing instruction as needed if the operand
2831 (assumed to be a MEM) is a volatile load. */
2832 case 'v': /* ditto for a volatile store. */
2833 if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE)
2835 /* The m88110 implements two FIFO queues, one for loads and
2836 one for stores. These queues mean that loads complete in
2837 their issue order as do stores. An interaction between the
2838 history buffer and the store reservation station ensures
2839 that a store will not bypass load. Finally, a load will not
2840 bypass store, but only when they reference the same address.
2842 To avoid this reordering (a load bypassing a store) for
2843 volatile references, a serializing instruction is output.
2844 We choose the fldcr instruction as it does not serialize on
2845 the m88100 so that -m88000 code will not be degraded.
2847 The mechanism below is completed by having CC_STATUS_INIT set
2848 the code to the unknown value. */
2852 A problem with 88110 4.1 & 4.2 makes the use of fldcr for
2853 this purpose undesirable. Instead we will use tb1, this will
2854 cause serialization on the 88100 but such is life.
2857 static rtx last_addr = 0;
2858 if (code == 'V' /* Only need to serialize before a load. */
2859 && m88k_volatile_code != 'V' /* Loads complete in FIFO order. */
2860 && !(m88k_volatile_code == 'v'
2861 && GET_CODE (XEXP (x, 0)) == LO_SUM
2862 && rtx_equal_p (XEXP (XEXP (x, 0), 1), last_addr)))
2866 "fldcr\t %s,%scr63\n\t",
2868 "fldcr\t %s,%sfcr63\n\t",
2870 reg_names[0], m88k_pound_sign);
2872 "tb1\t 1,%s,0xff\n\t", reg_names[0]);
2874 m88k_volatile_code = code;
2875 last_addr = (GET_CODE (XEXP (x, 0)) == LO_SUM
2876 ? XEXP (XEXP (x, 0), 1) : 0);
2880 case 'X': /* print the upper 16 bits... */
2882 case 'x': /* print the lower 16 bits of the integer constant in hex */
2883 if (xc != CONST_INT)
2884 output_operand_lossage ("invalid %%x/X value");
2885 fprintf (file, "0x%x", value & 0xffff); return;
2887 case 'H': /* print the low 16 bits of the negated integer constant */
2888 if (xc != CONST_INT)
2889 output_operand_lossage ("invalid %%H value");
2891 case 'h': /* print the register or low 16 bits of the integer constant */
2894 if (xc != CONST_INT)
2895 output_operand_lossage ("invalid %%h value");
2896 fprintf (file, "%d", value & 0xffff);
2899 case 'Q': /* print the low 8 bits of the negated integer constant */
2900 if (xc != CONST_INT)
2901 output_operand_lossage ("invalid %%Q value");
2903 case 'q': /* print the register or low 8 bits of the integer constant */
2906 if (xc != CONST_INT)
2907 output_operand_lossage ("invalid %%q value");
2908 fprintf (file, "%d", value & 0xff);
2911 case 'w': /* print the integer constant (X == 32 ? 0 : 32 - X) */
2912 if (xc != CONST_INT)
2913 output_operand_lossage ("invalid %%o value");
2914 fprintf (file, "%d", value == 32 ? 0 : 32 - value);
2917 case 'p': /* print the logarithm of the integer constant */
2919 || (value = exact_log2 (value)) < 0)
2920 output_operand_lossage ("invalid %%p value");
2921 fprintf (file, "%d", value);
2924 case 'S': /* compliment the value and then... */
2926 case 's': /* print the width and offset values forming the integer
2927 constant with a SET instruction. See integer_ok_for_set. */
2929 register unsigned mask, uval = value;
2930 register int top, bottom;
2932 if (xc != CONST_INT)
2933 output_operand_lossage ("invalid %%s/S value");
2934 /* All the "one" bits must be contiguous. If so, MASK will be
2935 a power of two or zero. */
2936 mask = (uval | (uval - 1)) + 1;
2937 if (!(uval && POWER_OF_2_or_0 (mask)))
2938 output_operand_lossage ("invalid %%s/S value");
2939 top = mask ? exact_log2 (mask) : 32;
2940 bottom = exact_log2 (uval & ~(uval - 1));
2941 fprintf (file,"%d<%d>", top - bottom, bottom);
2945 case 'P': /* print nothing if pc_rtx; output label_ref */
2946 if (xc == LABEL_REF)
2947 output_addr_const (file, x);
2949 output_operand_lossage ("invalid %%P operand");
2952 case 'L': /* print 0 or 1 if operand is label_ref and then... */
2953 fputc (xc == LABEL_REF ? '1' : '0', file);
2954 case '.': /* print .n if delay slot is used */
2955 fputs ((final_sequence
2956 && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
2957 ? ".n\t" : "\t", file);
2960 case '!': /* Reverse the following condition. */
2964 case 'R': /* reverse the condition of the next print_operand
2965 if operand is a label_ref. */
2967 reversep = (xc == LABEL_REF);
2970 case 'B': /* bcnd branch values */
2971 fputs (m88k_pound_sign, file);
2974 case EQ: fputs ("eq0", file); return;
2975 case NE: fputs ("ne0", file); return;
2976 case GT: fputs ("gt0", file); return;
2977 case LE: fputs ("le0", file); return;
2978 case LT: fputs ("lt0", file); return;
2979 case GE: fputs ("ge0", file); return;
2980 default: output_operand_lossage ("invalid %%B value");
2983 case 'C': /* bb0/bb1 branch values for comparisons */
2984 fputs (m88k_pound_sign, file);
2987 case EQ: fputs ("eq", file); return;
2988 case NE: fputs ("ne", file); return;
2989 case GT: fputs ("gt", file); return;
2990 case LE: fputs ("le", file); return;
2991 case LT: fputs ("lt", file); return;
2992 case GE: fputs ("ge", file); return;
2993 case GTU: fputs ("hi", file); return;
2994 case LEU: fputs ("ls", file); return;
2995 case LTU: fputs ("lo", file); return;
2996 case GEU: fputs ("hs", file); return;
2997 default: output_operand_lossage ("invalid %%C value");
3000 case 'D': /* bcnd branch values for float comparisons */
3003 case EQ: fputs ("0xa", file); return;
3004 case NE: fputs ("0x5", file); return;
3005 case GT: fputs (m88k_pound_sign, file);
3006 fputs ("gt0", file); return;
3007 case LE: fputs ("0xe", file); return;
3008 case LT: fputs ("0x4", file); return;
3009 case GE: fputs ("0xb", file); return;
3010 default: output_operand_lossage ("invalid %%D value");
3013 case 'E': /* bcnd branch values for special integers */
3016 case EQ: fputs ("0x8", file); return;
3017 case NE: fputs ("0x7", file); return;
3018 default: output_operand_lossage ("invalid %%E value");
3021 case 'd': /* second register of a two register pair */
3023 output_operand_lossage ("`%%d' operand isn't a register");
3024 fputs (reg_names[REGNO (x) + 1], file);
3027 case 'r': /* an immediate 0 should be represented as `r0' */
3028 if (x == const0_rtx)
3030 fputs (reg_names[0], file);
3034 output_operand_lossage ("invalid %%r value");
3040 if (REGNO (x) == ARG_POINTER_REGNUM)
3041 output_operand_lossage ("operand is r0");
3043 fputs (reg_names[REGNO (x)], file);
3045 else if (xc == PLUS)
3048 output_address (XEXP (x, 0));
3049 else if (flag_pic && xc == UNSPEC)
3051 output_addr_const (file, XVECEXP (x, 0, 0));
3052 fputs ("#got_rel", file);
3054 else if (xc == CONST_DOUBLE)
3055 output_operand_lossage ("operand is const_double");
3057 output_addr_const (file, x);
3060 case 'g': /* append #got_rel as needed */
3061 if (flag_pic && (xc == SYMBOL_REF || xc == LABEL_REF))
3063 output_addr_const (file, x);
3064 fputs ("#got_rel", file);
3069 case 'a': /* (standard), assume operand is an address */
3070 case 'c': /* (standard), assume operand is an immediate value */
3071 case 'l': /* (standard), assume operand is a label_ref */
3072 case 'n': /* (standard), like %c, except negate first */
3074 output_operand_lossage ("invalid code");
3079 print_operand_address (file, addr)
3083 register rtx reg0, reg1, temp;
3085 switch (GET_CODE (addr))
3088 if (REGNO (addr) == ARG_POINTER_REGNUM)
3091 fprintf (file, "%s,%s", reg_names[0], reg_names [REGNO (addr)]);
3095 fprintf (file, "%s,%slo16(",
3096 reg_names[REGNO (XEXP (addr, 0))], m88k_pound_sign);
3097 output_addr_const (file, XEXP (addr, 1));
3102 reg0 = XEXP (addr, 0);
3103 reg1 = XEXP (addr, 1);
3104 if (GET_CODE (reg0) == MULT || GET_CODE (reg0) == CONST_INT)
3111 if ((REG_P (reg0) && REGNO (reg0) == ARG_POINTER_REGNUM)
3112 || (REG_P (reg1) && REGNO (reg1) == ARG_POINTER_REGNUM))
3115 else if (REG_P (reg0))
3118 fprintf (file, "%s,%s",
3119 reg_names [REGNO (reg0)], reg_names [REGNO (reg1)]);
3121 else if (GET_CODE (reg1) == CONST_INT)
3122 fprintf (file, "%s,%d",
3123 reg_names [REGNO (reg0)], INTVAL (reg1));
3125 else if (GET_CODE (reg1) == MULT)
3127 rtx mreg = XEXP (reg1, 0);
3128 if (REGNO (mreg) == ARG_POINTER_REGNUM)
3131 fprintf (file, "%s[%s]", reg_names[REGNO (reg0)],
3132 reg_names[REGNO (mreg)]);
3135 else if (GET_CODE (reg1) == ZERO_EXTRACT)
3137 fprintf (file, "%s,%slo16(",
3138 reg_names[REGNO (reg0)], m88k_pound_sign);
3139 output_addr_const (file, XEXP (reg1, 0));
3145 fprintf (file, "%s,", reg_names[REGNO (reg0)]);
3146 output_addr_const (file, reg1);
3147 fputs ("#got_rel", file);
3157 if (REGNO (XEXP (addr, 0)) == ARG_POINTER_REGNUM)
3160 fprintf (file, "%s[%s]",
3161 reg_names[0], reg_names[REGNO (XEXP (addr, 0))]);
3165 fprintf (file, "%s,%d", reg_names[0], INTVAL (addr));
3169 fprintf (file, "%s,", reg_names[0]);
3170 if (SHORT_ADDRESS_P (addr, temp))
3172 fprintf (file, "%siw16(", m88k_pound_sign);
3173 output_addr_const (file, addr);
3177 output_addr_const (file, addr);
3181 /* Return true if X is an address which needs a temporary register when
3182 reloaded while generating PIC code. */
3185 pic_address_needs_scratch (x)
3188 /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */
3189 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
3190 && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
3191 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
3192 && ! ADD_INT (XEXP (XEXP (x, 0), 1)))
3198 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
3199 reference and a constant. */
3202 symbolic_operand (op, mode)
3204 enum machine_mode mode;
3206 switch (GET_CODE (op))
3214 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
3215 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
3216 && GET_CODE (XEXP (op, 1)) == CONST_INT);
3218 /* ??? This clause seems to be irrelevant. */
3220 return GET_MODE (op) == mode;
3227 #if defined (CTOR_LIST_BEGIN) && !defined (OBJECT_FORMAT_ELF)
3229 m88k_svr3_asm_out_constructor (symbol, priority)
3231 int priority ATTRIBUTE_UNUSED;
3233 const char *name = XSTR (symbol, 0);
3236 fprintf (asm_out_file, "\tor.u\t r13,r0,hi16(");
3237 assemble_name (asm_out_file, name);
3238 fprintf (asm_out_file, ")\n\tor\t r13,r13,lo16(");
3239 assemble_name (asm_out_file, name);
3240 fprintf (asm_out_file, ")\n\tsubu\t r31,r31,%d\n\tst\t r13,r31,%d\n",
3241 STACK_BOUNDARY / BITS_PER_UNIT, REG_PARM_STACK_SPACE (0));
3245 m88k_svr3_asm_out_destructor (symbol, priority)
3247 int priority ATTRIBUTE_UNUSED;
3252 assemble_integer (symbol, UNITS_PER_WORD, BITS_PER_WORD, 1);
3253 for (i = 1; i < 4; i++)
3254 assemble_integer (constm1_rtx, UNITS_PER_WORD, BITS_PER_WORD, 1);
3256 #endif /* INIT_SECTION_ASM_OP && ! OBJECT_FORMAT_ELF */
3259 m88k_select_section (decl, reloc, align)
3262 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
3264 if (TREE_CODE (decl) == STRING_CST)
3266 if (! flag_writable_strings)
3267 readonly_data_section ();
3268 else if (TREE_STRING_LENGTH (decl) <= m88k_gp_threshold)
3273 else if (TREE_CODE (decl) == VAR_DECL)
3275 if (SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)))
3277 else if ((flag_pic && reloc)
3278 || !TREE_READONLY (decl) || TREE_SIDE_EFFECTS (decl)
3279 || !DECL_INITIAL (decl)
3280 || (DECL_INITIAL (decl) != error_mark_node
3281 && !TREE_CONSTANT (DECL_INITIAL (decl))))
3284 readonly_data_section ();
3287 readonly_data_section ();
3290 /* Adjust the cost of INSN based on the relationship between INSN that
3291 is dependent on DEP_INSN through the dependence LINK. The default
3292 is to make no adjustment to COST.
3294 On the m88k, ignore the cost of anti- and output-dependencies. On
3295 the m88100, a store can issue two cycles before the value (not the
3296 address) has finished computing. */
3299 m88k_adjust_cost (insn, link, dep, cost)
3305 if (REG_NOTE_KIND (link) != 0)
3306 return 0; /* Anti or output dependence. */
3309 && recog_memoized (insn) >= 0
3310 && get_attr_type (insn) == TYPE_STORE
3311 && SET_SRC (PATTERN (insn)) == SET_DEST (PATTERN (dep)))
3312 return cost - 4; /* 88110 store reservation station. */
3317 /* For the m88k, determine if the item should go in the global pool. */
3320 m88k_encode_section_info (decl, first)
3322 int first ATTRIBUTE_UNUSED;
3324 if (m88k_gp_threshold > 0)
3326 if (TREE_CODE (decl) == VAR_DECL)
3328 if (!TREE_READONLY (decl) || TREE_SIDE_EFFECTS (decl))
3330 int size = int_size_in_bytes (TREE_TYPE (decl));
3332 if (size > 0 && size <= m88k_gp_threshold)
3333 SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
3336 else if (TREE_CODE (decl) == STRING_CST
3337 && flag_writable_strings
3338 && TREE_STRING_LENGTH (decl) <= m88k_gp_threshold)
3339 SYMBOL_REF_FLAG (XEXP (TREE_CST_RTL (decl), 0)) = 1;